#define FUSE_USE_VERSION 26
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stddef.h>
#include <unicode/utypes.h>
#include <unicode/ustring.h>
#include <pthread.h>
#include <time.h>
#include <errno.h>
#include <semaphore.h>
#include <signal.h>
#include "utils.h"
#include "fuse.h"
#include "unistd.h"
#include "list.h"
#include <unicode/utf16.h>

#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/un.h> 
#include <netinet/in.h> 
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/select.h>


#define FAT                             	0
#define ULTIMO_FAT                          1
#define BOOT                            	2
#define RTA_BOOT                           	3
#define HSOK	     			101
#define HSFAIL	     			102

// #define READ_SECTOR_REQUEST 100
// #define WRITE_SECTOR_REQUEST 99
// #define RTA_WRITE_SECTOR_REQUEST 98
#define READ_SECTOR_REQUEST_LAST 97
#define SET_SECTORES_LAST 96

#define READ_SECTOR_REQUEST 			200
#define WRITE_SECTOR_REQUEST 			201
#define RTA_READ_SECTOR_REQUEST 		300
#define RTA_WRITE_SECTOR_REQUEST 		301

#define HANDSHAKE 	10

#define		SET_SECTORES		73
#define		RTA_SET_SECTORES	74
#define NUMEROPEDIDO			70


typedef struct Informacion_IPC
{
	long payLoadLength;
	short payLoadDescriptor;
	char descriptorID[16];
	char *payload;
} InfoIPC;

int generarStructIPC(char *payload, short mode, InfoIPC *rInfoIPC)  /*sort es 2 bytes,int es 4 bytes,uso short porq no es necesario usar mas en este caso*/
{	
	char *descriptor = (char *) malloc(sizeof(char) * 16);
	GenerarDescriptor(&descriptor);
	strcpy(rInfoIPC->descriptorID,descriptor); /*creo el descriptor y lo cargo en la estructura. */
	rInfoIPC->payLoadDescriptor=mode; /*cargo el protocolo a la struct*/		
	if(payload!=NULL){
		rInfoIPC->payload = (void*) malloc(rInfoIPC->payLoadLength);
		memset(rInfoIPC->payload,'\0',rInfoIPC->payLoadLength);
		memcpy(rInfoIPC->payload,payload,rInfoIPC->payLoadLength); 
	}
	else{
		rInfoIPC->payload = (char*) malloc(5);
		memset(rInfoIPC->payload,'\0',rInfoIPC->payLoadLength);
		memcpy(rInfoIPC->payload,"nada",rInfoIPC->payLoadLength); 	
	}	
		

	return 0; 
}


int GenerarDescriptor(char **aux_descriptor){

	char descriptor[16];
	
	char cadena [] = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	int pos = 0;

 
	memset(descriptor, '\0', 16);

	for(pos = 0; pos < 15; descriptor[pos++] = cadena[(int)(rand()%62)]);
	descriptor[pos] = '\0';

    
	*aux_descriptor = descriptor;
	
	return 1;
}


int enviarIPC(int sock, InfoIPC *rInfoIPC)
{
	int tm;
	char *buffer;
	int bufLen;
	int length;

	bufLen = (sizeof(char) * strlen(rInfoIPC->descriptorID)) + sizeof(short) + sizeof(long) + sizeof(char)*rInfoIPC->payLoadLength + 20; /*Ese 20 no se de donde sale pero por las dudas lo dejo*/
	
	buffer	= (char*)malloc(bufLen);
	length =0;
	memcpy (buffer,&(rInfoIPC->payLoadLength),sizeof(long));
	length = sizeof(long);
	memcpy(buffer + length, &(rInfoIPC->payLoadDescriptor), sizeof(short));
	length += sizeof(short);
	memcpy(buffer + length, rInfoIPC->descriptorID, strlen(rInfoIPC->descriptorID)+1);
	length += strlen(rInfoIPC->descriptorID)+1;
	memcpy(buffer + length, rInfoIPC->payload, rInfoIPC->payLoadLength);
	length +=  rInfoIPC->payLoadLength; 
	
	tm = send(sock,buffer,length,0);
	return tm;
}


int recibirIPC(int sock, InfoIPC* rInfoIPC)
{
	int length;
	int len;
	char* buffer;
	char* payload;
	int ret;

	len = sizeof(short) + sizeof(long) + 16; /*tamaño del header, sin payload.*/

	buffer	= (char*) malloc(len);

	ret = recv(sock, buffer, len, 0);
	rInfoIPC->payLoadLength = 0;
	if(ret == len)
	{   
		length  = 0;
		rInfoIPC->payLoadLength =  *((long *) buffer);
		length += sizeof(long);

		rInfoIPC->payLoadDescriptor = *((short*) (buffer + length));
		length += sizeof(short);

		strncpy(rInfoIPC->descriptorID,(char*)( buffer + length),16);
		length += 16;
	}else return -1; /*retorno NOSERECIBIOLACANTDEDATOSAPROPIADA*/
	
	if(rInfoIPC->payLoadLength != 0)
	{
     
         payload	= (char*)malloc(sizeof(char) * rInfoIPC->payLoadLength);
     		
      /*recibirDatos(sock, payload, rInfoIPC->payLoadLength);*/
      ret = recv(sock, payload,  rInfoIPC->payLoadLength, 0);   /*fuerzo a recibir dos veces para que en la segunda reciba los datos(pero es un solo send del otro lado)*/	
  
         rInfoIPC->payload 	= (char*)malloc(sizeof(char) * rInfoIPC->payLoadLength);
     	
      memset(rInfoIPC->payload,'\0',rInfoIPC->payLoadLength);
		memcpy(rInfoIPC->payload,payload,rInfoIPC->payLoadLength);
		return 0;  /*retorno OK*/

   }else return HANDSHAKE;	
}	


int Conectar2 ( int iDescriptor_del_socket , char* sIP_remoto , int iPuerto_remoto_para_el_socket )
{
	struct sockaddr_in Str_sockaddr_in_paraConnect;/*estructura para el Connect*/

	Str_sockaddr_in_paraConnect.sin_family = AF_INET;/*estructura para el connect*/
	Str_sockaddr_in_paraConnect.sin_addr.s_addr = inet_addr (sIP_remoto);
	Str_sockaddr_in_paraConnect.sin_port = htons (iPuerto_remoto_para_el_socket);	
	memset (&(Str_sockaddr_in_paraConnect.sin_zero), 8, '\0');
	
	
	if ( connect ( iDescriptor_del_socket , (struct sockaddr *) & Str_sockaddr_in_paraConnect , sizeof (Str_sockaddr_in_paraConnect ) ) == -1 )/*conect & check*/
       {

		printf("error al conectar\n");

		return -1;
            }
	else
            {

		return 5;
            }
}

int crearSocket(int tipo){
	
    int sock;															  
    
    switch(tipo){
    
	case AF_INET:
	
	    if((sock = socket(tipo,SOCK_STREAM,0)) == -1){   
		return -1;														  
	    }
	
	    break;
	
	case AF_UNIX:
	    
	    if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
		return -1;
	    }  
	    
	    break;    
    }
    
    return sock;    
}

typedef struct BootRegion
{
    unsigned int bytes_per_sector;
    unsigned int sectors_per_cluster;	
    unsigned int count_sect_reservados;
    unsigned int num_fats;
    unsigned int total_sectors;
    unsigned int fat32_size;
    unsigned int first_data_sector;
    unsigned int cluster_size;
    unsigned int first_data_cluster;
    unsigned int count_clusters_fat;
} bootRegion;

//typedef char* sector;

typedef struct Sector
{
    char *sec;
}sector;

typedef struct Sectors
{
    sector *data;
    struct Sectors *sgt;
}sectors;

typedef u_int32_t clusterId;

typedef struct ClusterIds
{
  clusterId *data;
  struct ClusterIds *sgt;
}clusterIds;

typedef sectors cluster;  

typedef struct Clusters
{
  cluster *data;
  struct Clusters *sgt;
}clusters;


typedef unsigned int fatRegistry;


typedef struct CacheFatRegistry
{
   unsigned int pos;
   fatRegistry data;
}cacheFatRegistry;


typedef struct CacheFatRegistries
{
  cacheFatRegistry *data;
  struct CacheFatRegistries *sgt;
}cacheFatRegistries;


typedef unsigned int directoryType;

typedef struct DirectoryInput
{
    char longName[14];
    char *name;
    clusterId idCluster;
    directoryType type;
    char *ext;
    unsigned int size;
}directoryInput;

typedef struct DirectoryInputs
{
  directoryInput *data;
  //struct DirectoryInputs *content;
  struct DirectoryInputs *sgt;
}directoryInputs;

enum cluster_state {free_cluster, reserved, used, bad, last, error};


typedef struct Directory
{
  directoryInput *data;
  struct Directory *content;
  struct Directory *sgt;
}directory;


typedef struct CacheCluster {
//   char *file_path;
  unsigned int cluster_num;
  cluster *cluster_data;
}cacheCluster;


typedef struct CacheFile {
  char *path;
  unsigned int cant_opens;
//   sem_t write_semaphore;
  pthread_mutex_t write_mutex;
  unsigned int wrote;
  cacheCluster *cache;
}cacheFile;


typedef struct CacheFiles
{
  cacheFile *data;
  struct CacheFiles *sgt;
}cacheFiles;


typedef struct {
  uint8_t name[8];
  uint8_t ext[3];
  uint8_t type;
  uint64_t ocho_ceros;
  uint16_t high_first_cluster;
  uint32_t cuatro_ceros;
  uint16_t low_first_cluster;
  uint32_t size;
} __attribute__ ((packed)) directoryInputRegistry;


typedef struct NipcCluster{
    unsigned int sector_num;
    unsigned int offset;
    unsigned int size;
    int sock_desc;
    int wrote;
    char data[512];//[DISK_SECTOR_SIZE];
}nipcCluster;

// int readBootRegion(FILE* disk, bootRegion **boot);
int readBootRegion(FILE* disk, bootRegion *boot);
int readBootRegionField(FILE* disk, unsigned int *leer, unsigned int offset, unsigned int size, char *aux_data);
int loadFAT(FILE* disk, bootRegion *boot, fatRegistry *fatTable);
int loadSectorIntoFAT(FILE* disk, bootRegion *boot, unsigned int num_sector, fatRegistry *fatTable, unsigned int last_loaded, int iSocketConectado);

int readSector(FILE* disk, bootRegion* boot, unsigned int num_sector, unsigned int offset, unsigned int size, char** data_sector);
int readAllSector(FILE* disk, bootRegion *boot, char **data_sector, sectors *listSectors);
int loadFreeClusters(bootRegion *boot, fatRegistry *fatTable, char *freeClusters);
int addFreeClusters( char* freeClusters, clusterIds* listToAdd);
int deleteFreeClusters( char* freeClusters, clusterIds* listToDelete);
int readCluster(FILE* disk, bootRegion *boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors *listSectors);
int addDirectoryInputsFromSector(bootRegion *boot, char *data_sector, directoryInputs *dirs);
int addDirectoryInputsFromCluster(bootRegion *boot, cluster *dirCluster, directoryInputs *dirs);
int addDirectoryInputsFromLinkedClusters(FILE* disk, bootRegion *boot, fatRegistry *fatTable, unsigned int cluster_num, directoryInputs *dirs);
int addDirectoryContent(directory *direct, directoryInputs *dirs);
int addDirectory(FILE* disk, bootRegion *boot, fatRegistry *fatTable, unsigned int cluster_num, directory *direct);
int addDirectoryTree(FILE* disk, bootRegion *boot, fatRegistry *fatTable, unsigned int cluster_num, directory *direct, int level);

//int searchDirectory(directory *dir, char* name,directory *result);
//int cutPath(const char *path,char *directory[]);

int readFileFromLinkedClusters(FILE* disk, bootRegion* boot, fatRegistry* fatTable, const char* path, unsigned int cluster_num, unsigned int offset, unsigned int size, char** content, unsigned int *newSize);
int writeSector(FILE* disk, bootRegion *boot, unsigned int num_sector, unsigned int offset, unsigned int size, char *data_sector);
int writeCluster(FILE* disk, bootRegion *boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors *listSectors);
// int getFileSize(FILE* disk, bootRegion *boot, fatRegistry *fatTable, const char *path, unsigned int cluster_num, int *size);
int truncateCluster(sectors *listSectors, int offset);
int truncateSector(char **data_sector, int offset);
int increaseCluster(sectors *listSectors, int offset, int final_byte);
int increaseSector(char **data_sector, int offset, int final_byte);
int getClusterState(fatRegistry* fatTable, unsigned int cluster_num, enum cluster_state *state, unsigned int *cluster_registry);
int saveFAT(FILE* disk, bootRegion *boot, fatRegistry *fatTable);
int writeSectorFromFAT(FILE* disk, bootRegion* boot, unsigned int num_sector, fatRegistry* fatTable, unsigned int last_loaded, int iSocketConectado);
int setFreeCluster(char* freeClusters, unsigned int cluster_num);
int getFreeCluster(char* freeClusters, unsigned int *cluster_num);
int setUsedCluster(char *freeClusters, unsigned int content, unsigned int cluster_num);
int fillWithChar(char **string, char fill_char, int total_size);
int writeFileFromLinkedClusters(FILE *disk, bootRegion *boot, const char *path, fatRegistry *fatTable, unsigned int cluster_num, unsigned int offset, unsigned int size, const char *content, unsigned int *wrote);
int charToListSectors(char *buf, unsigned int offset, unsigned int size, sectors **listSectors);
int createNullCluster(sectors **listSectors);
int createDirectoryInput(char **data_dir32, directoryInput *dir);
int createLongNameInput(char **data_dir32, directoryInput *dir);
int saveDirectoryInputIntoLinkedClusters(unsigned int cluster_num, char *new_dir_input, unsigned int mode);
int saveDirectoryInputIntoCluster(cluster *dirCluster, char *new_dir_input, unsigned int mode);
int saveDirectoryInputIntoSector(char **data_sector, char *new_dir_input, unsigned int mode);

char* rtrimHOTFAT(char* string, char junk);
char* ltrimHOTFAT(char *string, char junk);
int cutPath2(const char *path,char *directory,char* finalPath);
int newName(const char* path, char *name);
int fatherName(const char *path,char *fatherPath);
int searchPath(directory *dir, char* name, directory **result);
int searchPath2(directory *dir, char* name, directory **result, directory **last);
int searchDirectory(const char *path,directory *root, directory **dir);
int getDirectory(const char* path, directory *root, directory **dir);


int readSectorFAT(FILE* disk, bootRegion *boot, unsigned int num_sector, unsigned int offset, unsigned int size, char **data_sector, int iSocketConectado);
int readClusterNIPC(FILE* disk, bootRegion* boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors);
int writeClusterNIPC(FILE* disk, bootRegion* boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors);
int writeSectorFAT(FILE* disk, bootRegion *boot, unsigned int num_sector, unsigned int offset, unsigned int size, char *data_sector, int iSocketConectado);

int fsinfo();
int finfo(const char *path);

// ********** CACHE **********
int loadCacheFAT(FILE* disk, bootRegion *boot, cacheFatRegistries *cacheFatTable, unsigned int initial_sector, unsigned int final_sector);
int loadSectorIntoCacheFAT(FILE* disk, bootRegion *boot, unsigned int num_sector, cacheFatRegistries *cacheFatTable, unsigned int index);

int createCacheFile(const char *path, int fi_flags);
int releaseCacheFile(const char* path, int fi_flags);

int readClusterFromCache(FILE* disk, bootRegion* boot, const char *path, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors);
int writeClusterIntoCache(FILE* disk, bootRegion* boot, const char *path, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors);

// int readCacheCluster(unsigned int cache_pos, unsigned int offset, unsigned int size, sectors* listSectors);
// int writeCacheCluster(unsigned int cache_pos, const char *path, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors);
int writeCacheCluster(cluster **cluster_data, const char *path, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors);
int readCacheCluster(cluster *cluster_data, unsigned int offset, unsigned int size, sectors* listSectors);

int flushCache(const char *path);

void cacheDump(int signal);

// ********** FUSE_FUNCTIONS **********
static void * hotfat_fuse_main(void*);
int hotfat_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi);
int hotfat_open(const char *path, struct fuse_file_info *fi);
int hotfat_getattr(const char *path, struct stat *stbuf);
int hotfat_rename(const char *path, const char *newpath);
int hotfat_truncate(const char *path, off_t offset);
int hotfat_create(const char *path, mode_t mode, struct fuse_file_info *fi);
// int hotfat_mknod(const char *path, mode_t mode , dev_t dev); 
void hotfat_fullpath(char fpath[256], const char *path);
int hotfat_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi);
int hotfat_write(const char* path, const char* buf, size_t size, off_t offset, struct fuse_file_info* fi);
int hotfat_flush(const char *path, struct fuse_file_info *fi);
int hotfat_release(const char *path, struct fuse_file_info *fi);
int hotfat_mkdir(const char *path, mode_t mode); 
int hotfat_rmdir(const char* path);
int hotfat_unlink(const char *path);

int youMakeMeFiller(directory *dir,void *buf,fuse_fill_dir_t *filler);
int getAttrOfDir(directory *dir, const char *path,struct stat *stbuf);

struct fuse_operations x;

struct bb_state {
    FILE *logfile;
    char *rootdir;
};

directory *root = NULL;
bootRegion *boot;
FILE *disk;
fatRegistry *fatTablePointer;
char *freeClusters;

unsigned int cache_size = 32768;
cacheCluster *cache;
unsigned int cant_cache_clusters;
unsigned int cache_enabled;

cacheFiles *fileDescriptorsTable;
u_int8_t *modifyPointer;

char *ipDisco;
int puertoDisco;

int clusters_loaded_FAT;

int main(int argc, char *argv[])
{
    int i;
    pthread_t fuseThreadID;
    
    ipDisco = (char *) malloc (sizeof(char) * 16);
    strcpy(ipDisco, (char *)"192.168.240.128");
    puertoDisco = 8010;
    clusters_loaded_FAT = 0;
    
    x.readdir = hotfat_readdir;
    x.open = hotfat_open;
    x.getattr = hotfat_getattr;
    x.read = hotfat_read;
    x.rename = hotfat_rename;
    x.truncate = hotfat_truncate;
    x.create = hotfat_create;
    x.write = hotfat_write;
    x.flush = hotfat_flush;
    x.release = hotfat_release;
    x.mkdir = hotfat_mkdir;
    x.rmdir = hotfat_rmdir;
    x.unlink = hotfat_unlink;
    
    
    
    
    boot = (bootRegion *) malloc (sizeof(bootRegion));

    disk = fopen("/home/utn_so/fat32_legui.disk", "r+");
    
    readBootRegion(disk, boot);
        
    printf("bytes_per_sector: %i\n", boot->bytes_per_sector);
    printf("sectors_per_cluster: %i\n", boot->sectors_per_cluster);
    printf("count_sect_reservados: %i\n", boot->count_sect_reservados);
    printf("count_fats: %i\n", boot->num_fats);
    printf("total_sectors: %i\n", boot->total_sectors);
    printf("fat32_size: %i\n", boot->fat32_size);
    printf("cluster_size: %i\n", boot->cluster_size);
    printf("First_data_sector: %i\nNro Byte: %i\n", boot->first_data_sector, boot->first_data_sector * boot->bytes_per_sector);
    printf("First_data_cluster: %i\n", boot->first_data_cluster);
    
    
    fatRegistry fatTable[boot->count_clusters_fat];
    uint8_t modify[boot->count_clusters_fat];
    
//     char *data_sector;
//     readSector(disk, boot, 0, 0, boot->bytes_per_sector, &data_sector);
    
    
    
//     unsigned int initial_sector = 0;
//     unsigned int final_sector = 10;
    
    
    
    loadFAT(disk, boot, fatTable);
    
    printf("FatTable: \n");
    for(i=0;i< clusters_loaded_FAT;i++)
	if(fatTable[i]!=0)
	    printf("%u %x\n",i,fatTable[i]);
    
	
//     fatTablePointer = (fatRegistry *) malloc (sizeof(fatRegistry) * count_clusters_fat);
//     int w;
//     for(w=0;w<count_clusters_fat;w++)
//     {
// 	fatTablePointer[w] = fatTable[w];
//     }
	    
    int m;
    for(m=0;m<boot->count_clusters_fat;m++)
	modify[m]=0;
    
    modifyPointer = modify;
	    
    fatTablePointer = fatTable;
    freeClusters = (char *) malloc (sizeof(char) * boot->count_clusters_fat);
    loadFreeClusters(boot, fatTable, freeClusters);

    
    root = (directory *) malloc (sizeof(directory));
    
    root->data = (directoryInput *) malloc (sizeof(directoryInput));
    root->data->name = (char *) malloc (sizeof(char) * 14); //sizeof(char));
    strcpy(root->data->name, "root");
    root->data->ext = "";
    root->data->idCluster = 2;
    root->data->type = 16;
    root->data->size = 0;
    root->content = NULL;
    root->sgt = NULL;
// 	root->data->longName = (char *) malloc(sizeof(char)*14);
	strcpy(root->data->longName,"/");
    
    addDirectoryTree(disk, boot, fatTable, root->data->idCluster, root, -1);
    
    cant_cache_clusters = cache_size / boot->cluster_size;
    if(cant_cache_clusters > 0)
    {	
// 	cache = (cacheCluster *) malloc (cant_cache_clusters * sizeof(cacheCluster));
// 	for(i=0;i<cant_cache_clusters;i++)
// 	{
// 	    cache[i].cluster_data = (cluster *) malloc (sizeof(cluster));
// 	    cache[i].cluster_data->data = NULL;
// 	    cache[i].cluster_data->sgt = NULL;
// 	}
	cache_enabled = 1;
	signal(SIGUSR1, cacheDump);
	//system("handle SIGUSR1 ignore");
    }
    else
	cache_enabled = 0;
    
    
    fileDescriptorsTable = (cacheFiles *) malloc(sizeof(cacheFiles));
    fileDescriptorsTable->data = NULL;
    fileDescriptorsTable->sgt = NULL;
	
	
	
// 	char *longNameInput = (char *) malloc(sizeof(char)*33);
// 	
// 	createLongNameInput(&longNameInput,root->content->data);
// 	int l;
// 	printf("LongName:\n");
// 	for(l=0;l<32;l++)
// 	{
// 		printf("%c",longNameInput[l]);
// 	}
// 	


// 	// 		El utf16_str_len es el  de la cadena en utf16. Un ej:
// 	char cadenaEnUTF16[] = { 'a', '\0', 'l', '\0', 'g', '\0', 'o', '\0', '\0', '\0' };
// 	int lenUTF16 = 10;
// 	char cadenaEnUTF8[lenUTF16/2];
// 	int lenUTF8 = 0;
// 	unicode_utf16_to_utf8_inbuffer(cadenaEnUTF16, lenUTF16, cadenaEnUTF8, &lenUTF8);
// 	printf("utf8: %s\n",cadenaEnUTF8);
// 	
// 	int len = u_strlen(cadenaEnUTF16);
// 
// 	printf("Len: %i\n",len);
	
	

	// 		El utf16_str_len es el  de la cadena en utf16. Un ej:
// 	char cadenaEnUTF16[] = { 'n', '\0', 'o', '\0', 'm', '\0', 'b', '\0', 'r', '\0' ,'e','\0' ,'l','\0' ,'a','\0' ,'r','\0' ,'g','\0','o','\0','\0','\0'   };
// 	int lenUTF16 = u_strlen(cadenaEnUTF16);
// 	char *cadenaEnUTF8 = (char *) malloc(sizeof(char)*((lenUTF16)+1));
// 	//char cadenaEnUTF8[lenUTF16/2];
// 	int lenUTF8 = 0;
// 	unicode_utf16_to_utf8_inbuffer(cadenaEnUTF16, lenUTF16*2, cadenaEnUTF8, &lenUTF8);
// 	printf("utf8: %s\n",cadenaEnUTF8);
// 	
// 	int len = u_strlen(cadenaEnUTF16);
// 
// 	printf("Len: %i\n",len);
	
	
    
    
//     /**CONNECT**/
//     t_socket_client *client = sockets_createClient("10.0.2.15",atoi("8000") + 1);
//     sockets_connect(client, ipDisco, 9000);
//     
//     /**Handshake**/
//     t_nipc *nipc = (t_nipc *) nipc_create(NIPC_HANDSHAKE);
//     nipc_setdata(nipc, (char *)strdup("PFS"), strlen("PFS") + 1);
// 
//     nipc_send(nipc, client);
// 
//     nipc_destroy(nipc);
//     t_socket_buffer *buffer = (t_socket_buffer *)sockets_recv(client);
//     nipc = (t_nipc *)nipc_deserializer(buffer, 0);
//     sockets_bufferDestroy(buffer);
//     nipc_destroy(nipc);
   
    
	void *param = NULL;
	hotfat_fuse_main(param);
//     printf("\nLanzando el thread para FUSE\n\n");
//     if(pthread_create(&fuseThreadID, NULL, hotfat_fuse_main, NULL) != 0)
//     {
// 		printf("\nError al crear el hilo");
//     }    
    
    
//     if (pthread_join(fuseThreadID, NULL))
//     {
//         perror("Tread joining:");
//         exit(1);
//     }
    
    
    
    directory *qdir;
    while(root->content != NULL)
    {
	qdir = root->content;
	root->content = root->content->sgt;
	free(qdir->data->name);
	free(qdir->data->ext);
	free(qdir->data);
	free(qdir);
    }
    free(root->data->name);
    free(root->data);
    free(root);
    
    free(boot);
    free(disk);
    
    printf("Terminamos\n");
    
    return 1;
}


static void * hotfat_fuse_main(void *param)
{
    struct bb_state *bb_data;
    
    bb_data = (struct bb_state *) malloc(sizeof(struct bb_state));
    bb_data->rootdir = (char *) malloc(sizeof(char) * 256);//sizeof(char));
    bb_data->rootdir = realpath("/home/utn_so/pruebasL/prueba1/chelo", NULL);
    
    
    int argc2 = 2;
    char *argv2[] = { "/home/utn_so/fat32_legui.disk" , "/home/utn_so/pruebasL/prueba1/chelo" , "-d"};

    fuse_main(3,argv2,&x,bb_data);
    
    free(bb_data->rootdir);
    free(bb_data);
    
    return NULL;
}


int loadFreeClusters(bootRegion *boot, fatRegistry *fatTable, char *freeClusters)
{
    int i;
    
    for (i = 0;(i< (boot->fat32_size * boot->bytes_per_sector)/4) && (i<clusters_loaded_FAT);i++)
    {
	if(!(fatTable[i]))
	    freeClusters[i] = '0';
	else
	    freeClusters[i] = '1';
    }
    
    return 1;
}

int addFreeClusters(char *freeClusters, clusterIds *listToAdd)
{
    int i = 0;
    clusterIds *q = listToAdd;
    for(i=0;q!=NULL;i++)
    {
      clusterIds *aux = q->sgt;
      
      freeClusters[*(q->data)] = '0';
      q = aux;
    }
}

int deleteFreeClusters(char *freeClusters, clusterIds *listToDelete)
{
    int i = 0;
    clusterIds *q = listToDelete;
    for(i=0;q!=NULL;i++)
    {
      clusterIds *aux = q->sgt;
      freeClusters[*(q->data)] = '1';
      q = aux;
    }
}

int loadFAT(FILE* disk, bootRegion *boot, fatRegistry *fatTable)
{
    if(clusters_loaded_FAT < boot->count_clusters_fat)
    {
	unsigned int last_loaded, num_sector;
	int i;
	
	num_sector = boot->count_sect_reservados;// + 1;
	
	int iSocketConectado = crearSocket(AF_INET);
	Conectar2(iSocketConectado, ipDisco, puertoDisco);	
	
	InfoIPC rInfoIPC;
// 	char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int)+ 1);
	
	rInfoIPC.payLoadLength = 5;
	generarStructIPC("nada",HANDSHAKE,&rInfoIPC);
	
	enviarIPC(iSocketConectado,&rInfoIPC);
	
	recibirIPC(iSocketConectado,&rInfoIPC);
	if(rInfoIPC.payLoadDescriptor == HSOK)
	{
	    
// 	    last_loaded = 0;
// 	    for (i = 0;i< boot->fat32_size;i++)
// 	    {
// 		loadSectorIntoFAT(disk, boot, num_sector + i, fatTable, last_loaded, iSocketConectado);
// 		last_loaded += (boot->bytes_per_sector/4);
// 	    }

	    i = clusters_loaded_FAT / (boot->bytes_per_sector/4);
	    loadSectorIntoFAT(disk, boot, num_sector + i, fatTable, clusters_loaded_FAT, iSocketConectado);
	    clusters_loaded_FAT += (boot->bytes_per_sector/4);

	}
    
	close(iSocketConectado);
	
    }   
    return 1;
}


int loadSectorIntoFAT(FILE* disk, bootRegion *boot, unsigned int num_sector, fatRegistry *fatTable, unsigned int last_loaded, int iSocketConectado)
{
    int i,j;
    char *data_sector;
    data_sector = (char *) malloc(sizeof(char) * 512);
    
    readSectorFAT(disk, boot, num_sector, 0, boot->bytes_per_sector, &data_sector, iSocketConectado);
    
    for (i = 0,j=last_loaded;i< boot->bytes_per_sector;i+=4,j++)
    {
	memcpy(&fatTable[j],&data_sector[i],4);
    }
    
    free(data_sector);
    
    return 1;
}

int loadCacheFAT(FILE* disk, bootRegion* boot, cacheFatRegistries* cacheFatTable, unsigned int initial_sector, unsigned int final_sector)
{
    unsigned int index, num_sector;
    int i;
    
    num_sector = boot->count_sect_reservados + initial_sector;
    
    index = 0 + initial_sector * (boot->bytes_per_sector / 4);
    for (i = 0;(i < (final_sector - initial_sector)) && (i< boot->fat32_size) ;i++)
    {
	loadSectorIntoCacheFAT(disk, boot, num_sector + i, cacheFatTable, index);
	index += (boot->bytes_per_sector/4);
    }

    return 1;
}

int loadSectorIntoCacheFAT(FILE* disk, bootRegion *boot, unsigned int num_sector, cacheFatRegistries *cacheFatTable, unsigned int index)
{
    int i,j;
    char *data_sector;
    data_sector = (char *) malloc(sizeof(char) * 512);
    
    readSector(disk, boot, num_sector, 0, boot->bytes_per_sector, &data_sector);
    
    for (i = 0,j=index;i< boot->bytes_per_sector;i+=4,j++)
    {
	cacheFatRegistry *aux_registry = (cacheFatRegistry *) malloc (sizeof(cacheFatRegistry));
	
	aux_registry->pos = j;
	memcpy(&(aux_registry->data),&data_sector[i],4);
	
	addToList((gl *)cacheFatTable, aux_registry);
	
	
    }
    
    free(data_sector);
    
    
    return 1;
}



// int readBootRegion(FILE* disk, bootRegion **boot)
int readBootRegion(FILE* disk, bootRegion *boot)
{
    
    char *aux_data = (char *) malloc(sizeof(char) * 512);
    readSector(disk, boot, 0, 0, 512, &aux_data);
    
    readBootRegionField(disk, &(boot->bytes_per_sector), (unsigned int)0x0B, 2, aux_data);
    readBootRegionField(disk, &(boot->sectors_per_cluster) , (unsigned int)0x0D, 1, aux_data);
    readBootRegionField(disk, &(boot->count_sect_reservados) , (unsigned int)0x0E, 2, aux_data);
    readBootRegionField(disk, &(boot->num_fats), (unsigned int)0x10, 1, aux_data);
    readBootRegionField(disk, &(boot->total_sectors) , (unsigned int)0x20, 4, aux_data);
    readBootRegionField(disk, &(boot->fat32_size), (unsigned int)36, 4, aux_data);
    
    boot->first_data_sector = boot->count_sect_reservados + (boot->num_fats * boot->fat32_size);
    
    boot->cluster_size = boot->bytes_per_sector * boot->sectors_per_cluster;
    boot->first_data_cluster = boot->first_data_sector / boot->sectors_per_cluster;
    
    boot->count_clusters_fat = (boot->fat32_size * boot->bytes_per_sector) / 4;
    
    free(aux_data);
    
    return 1;
}

int readBootRegionField(FILE* disk, unsigned int *leer, unsigned int offset, unsigned int size, char *aux_data)
{
    unsigned int *aux_leer;
    aux_leer = (unsigned int*) malloc(sizeof(unsigned int));
    memset(aux_leer, 0, sizeof(unsigned int));
    
    memcpy(aux_leer, aux_data + offset, size);
    
    *leer = aux_leer[0];
    return 1;
}


int readClusterNIPC(FILE* disk, bootRegion* boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
{

    
    unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size, i = 0;
    
    div_sectors_int = offset / boot->bytes_per_sector;
    div_sectors_resto = offset % boot->bytes_per_sector;
    
    div_total_size_int = size / boot->bytes_per_sector;
    div_total_size_resto = size % boot->bytes_per_sector;
    
    if(div_total_size_int > 0 && div_total_size_resto == 0)
    {
	div_total_size_resto = boot->bytes_per_sector;
	div_total_size_int--;
    }
    
    while(i < div_sectors_int)
	i++;
    
    int iSocketConectado = crearSocket(AF_INET);
    Conectar2(iSocketConectado, ipDisco, puertoDisco);	
    
    InfoIPC hsInfoIPC;
    
    hsInfoIPC.payLoadLength = 5;
    generarStructIPC("nada",HANDSHAKE,&hsInfoIPC);
    enviarIPC(iSocketConectado,&hsInfoIPC);
    
    recibirIPC(iSocketConectado,&hsInfoIPC);
    if(hsInfoIPC.payLoadDescriptor == HSOK)
    {
	nipcCluster *cluster_data = (nipcCluster *) malloc ((boot->sectors_per_cluster - i) * sizeof(nipcCluster));
	int cant = 0;
	while(i<boot->sectors_per_cluster && i<= div_total_size_int)
	{
	    if(i == div_total_size_int)
		aux_size = div_total_size_resto;
	    else
		aux_size = boot->bytes_per_sector;
	    
	    cluster_data[cant].sector_num = i + (num_cluster * boot->sectors_per_cluster);
	    cluster_data[cant].offset = div_sectors_resto;
	    cluster_data[cant].size = aux_size;

	    char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int) + 1);
	    InfoIPC sInfoIPC;
	    memset(num_sector_str, '\0', sizeof(char) * sizeof(unsigned int) + 1);
	    sprintf(num_sector_str, "%u", cluster_data[cant].sector_num);
	    sInfoIPC.payLoadLength = strlen(num_sector_str) + 1;
	    generarStructIPC(num_sector_str,READ_SECTOR_REQUEST_LAST,&sInfoIPC);
	    enviarIPC(iSocketConectado ,&sInfoIPC);
	    free(num_sector_str);
	    cant++;
	    
	    div_sectors_resto = 0;
	    i++;
	}
	

	fd_set set_socket;
	FD_SET(iSocketConectado, &set_socket);

	struct timeval timeout;
	int rv;
	
	timeout.tv_sec = 3;
	timeout.tv_usec = 0;

	int j=0;
	int w=0;
	i=0;
	
	while(w < cant)
	{
	    FD_ZERO(&set_socket);
	    FD_SET(iSocketConectado, &set_socket);
	    rv = select(iSocketConectado+1, &set_socket, NULL, NULL, &timeout);
	    if(rv == -1)
	    {
		printf("Llamada del Select error\n");
		FD_CLR(iSocketConectado, &set_socket);
		free(cluster_data);
		return -1;
	    }
	    if(rv == 0)
		break;

	    if(FD_ISSET(iSocketConectado, &set_socket))
	    {
		InfoIPC rInfoIPC;
		unsigned int nro_pedido, nro_sector;
		recibirIPC(iSocketConectado,&rInfoIPC);
		if(rInfoIPC.payLoadDescriptor == NUMEROPEDIDO)
		{
		    nro_pedido = atoi(rInfoIPC.payload);
		
		    recibirIPC(iSocketConectado,&rInfoIPC);
		    if(rInfoIPC.payLoadDescriptor == RTA_READ_SECTOR_REQUEST)
		    {
			nro_sector = atoi(rInfoIPC.payload);
			recibirIPC(iSocketConectado,&rInfoIPC);
			for(j=0;j<cant;j++)
			    if(cluster_data[j].sector_num == nro_sector)
			    {
				memcpy(cluster_data[j].data, rInfoIPC.payload, rInfoIPC.payLoadLength);
			    }
			w++;
		    }
		    else
		    {
			rv = 0;
			break;
		    }
		}
		else
		{
		    rv = 0;
		    break;
		}
	    }
	
	    FD_CLR(iSocketConectado, &set_socket);
	}
	
	close(iSocketConectado);
	    
	int retv = 0;
	if(w < cant && rv == 0)
	    retv = readClusterNIPC(disk, boot, num_cluster, offset, size, listSectors);
	else
	{
	    for(i=0;i<cant;i++)
	    {
		sector *aux_sec = (sector *) malloc (sizeof(sector));
		aux_sec->sec = (char *) malloc(sizeof(char) * boot->bytes_per_sector);
		memcpy(aux_sec->sec, cluster_data[i].data + cluster_data[i].offset, (cluster_data[i].size - cluster_data[i].offset));
		addToList((gl *)listSectors,aux_sec);
	    }
	}
	free(cluster_data);
    }
    else
    {
	printf("Error al conectar\n");
	close(iSocketConectado);
	return -1;
    }

    return 1;
}

// int readClusterNIPC(FILE* disk, bootRegion* boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
// {
// 
//     
//     unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size, i = 0;
//     
//     div_sectors_int = offset / boot->bytes_per_sector;
//     div_sectors_resto = offset % boot->bytes_per_sector;
//     
//     div_total_size_int = size / boot->bytes_per_sector;
//     div_total_size_resto = size % boot->bytes_per_sector;
//     
//     if(div_total_size_int > 0 && div_total_size_resto == 0)
//     {
// 	div_total_size_resto = boot->bytes_per_sector;
// 	div_total_size_int--;
//     }
//     
//     while(i < div_sectors_int)
// 	i++;
//     
//     nipcCluster *cluster_data = (nipcCluster *) malloc ((boot->sectors_per_cluster - i) * sizeof(nipcCluster));
//     int cant = 0;
//     while(i<boot->sectors_per_cluster && i<= div_total_size_int)
//     {
// 	if(i == div_total_size_int)
// 	    aux_size = div_total_size_resto;
// 	else
// 	    aux_size = boot->bytes_per_sector;
// 	
// 	cluster_data[cant].sector_num = i + (num_cluster * boot->sectors_per_cluster);
// 	cluster_data[cant].offset = div_sectors_resto;
// 	cluster_data[cant].size = aux_size;
// 
// 	cluster_data[cant].sock_desc = crearSocket(AF_INET);
// 	Conectar2(cluster_data[cant].sock_desc, ipDisco, puertoDisco);	
// 	
// 	InfoIPC hsInfoIPC;
// 	
// 	hsInfoIPC.payLoadLength = 5;
// 	generarStructIPC("nada",HANDSHAKE,&hsInfoIPC);
// 	enviarIPC(cluster_data[cant].sock_desc,&hsInfoIPC);
// 	
// 	recibirIPC(cluster_data[cant].sock_desc,&hsInfoIPC);
// 	if(hsInfoIPC.payLoadDescriptor == HSOK)
// 	{
// 	    char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int) + 1);
// 	    InfoIPC sInfoIPC;
// 	    memset(num_sector_str, '\0', sizeof(char) * sizeof(unsigned int) + 1);
// 	    sprintf(num_sector_str, "%u", cluster_data[cant].sector_num);
// 	    sInfoIPC.payLoadLength = strlen(num_sector_str) + 1;
// 	    generarStructIPC(num_sector_str,READ_SECTOR_REQUEST_LAST,&sInfoIPC);
// 	    enviarIPC(cluster_data[cant].sock_desc ,&sInfoIPC);
// 	    free(num_sector_str);
// 	    cant++;
// 	}
// 	else
// 	{
// 	    printf("Error al conectar\n");
// 	    int counter = 0;
// 	    while(counter < cant)
// 	    {
// 		close(cluster_data[counter].sock_desc);
// 		counter++;
// 	    }
// 	    free(cluster_data);
// 	    return -1;
// 	}
// 	
// 	div_sectors_resto = 0;
// 	i++;
//     }
//     
// 
//     int sock_desc = crearSocket(AF_INET);
//     Conectar2(sock_desc, ipDisco, puertoDisco);
//     
//     InfoIPC hsInfoIPC;
//     hsInfoIPC.payLoadLength = 5;
//     generarStructIPC("nada",HANDSHAKE,&hsInfoIPC);
//     enviarIPC(sock_desc,&hsInfoIPC);
//     
//     recibirIPC(sock_desc,&hsInfoIPC);
//     
//     unsigned int max_sock = 0;
//     fd_set set_socket;
//     for(i=0;i<cant;i++)
//     {
// 	if(cluster_data[i].sock_desc > 0)
// 	{
// 	    FD_SET(cluster_data[i].sock_desc, &set_socket);
// 	    if(cluster_data[i].sock_desc > max_sock)
// 		max_sock = cluster_data[i].sock_desc;
// 	}
//     }
// 
//     struct timeval timeout;
//     int rv;
//     
//     timeout.tv_sec = 3;
//     timeout.tv_usec = 0;
// 
//     int j=0;
//     int w=0;
//     int done = 0;
//     i=0;
//     
//     while(w < cant)
//     {
// 	rv = select(max_sock+1, &set_socket, NULL, NULL, &timeout);
// 	if(rv == -1){
// 	    printf("Llamada del Select error\n");
// 	    int counter = 0;
// 	    while(counter < cant)
// 	    {
// 		FD_CLR(cluster_data[counter].sock_desc, &set_socket);
// 		close(cluster_data[counter].sock_desc);
// 		counter++;
// 	    }
// 	    free(cluster_data);
// 	    return -1;
// 	}
// 	if(rv == 0)
// 	    break;
// 
// 	i=0;
// 	done = 0;
// 	while(i < cant && done == 0)
// 	{
// 	    if(FD_ISSET(cluster_data[i].sock_desc, &set_socket))
// 	    {
// 		InfoIPC rInfoIPC;
// 		recibirIPC(cluster_data[i].sock_desc,&rInfoIPC);
// 		for(j=0;j<cant;j++)
// 		    if(cluster_data[j].sector_num == cluster_data[i].sector_num)
// 			memcpy(cluster_data[j].data, rInfoIPC.payload, rInfoIPC.payLoadLength);
// 		    
// 		FD_CLR(cluster_data[i].sock_desc, &set_socket);
// 		close(cluster_data[i].sock_desc);
// 		w++;
// 		done = 1;
// 	    }
// 	    i++;
// 	}
//     }
//     
//     close(sock_desc);
// 	
//     int retv = 0;
//     if(w < cant && rv == 0)
//     {
// 	int counter = 0;
// 	while(counter < cant)
// 	{
// 	    close(cluster_data[counter].sock_desc);
// 	    counter++;
// 	}
// 	retv = readClusterNIPC(disk, boot, num_cluster, offset, size, listSectors);
//     }
//     else
//     {
// 	for(i=0;i<cant;i++)
// 	{
// 	    sector *aux_sec = (sector *) malloc (sizeof(sector));
// 	    aux_sec->sec = (char *) malloc(sizeof(char) * boot->bytes_per_sector);
// 	    memcpy(aux_sec->sec, cluster_data[i].data + cluster_data[i].offset, (cluster_data[i].size - cluster_data[i].offset));
// 	    addToList((gl *)listSectors,aux_sec);
// 	}
//     }
//     free(cluster_data);
//     
//     return 1;
// }

int readSector(FILE* disk, bootRegion *boot, unsigned int num_sector, unsigned int offset, unsigned int size, char **data_sector)
{
    
	int iSocketConectado = crearSocket(AF_INET);
	Conectar2(iSocketConectado, ipDisco, puertoDisco);	
	
	InfoIPC rInfoIPC;
	char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int)+ 1);
	
	rInfoIPC.payLoadLength = 5;
	generarStructIPC("nada",HANDSHAKE,&rInfoIPC);
	
	enviarIPC(iSocketConectado,&rInfoIPC);
	
	recibirIPC(iSocketConectado,&rInfoIPC);
	if(rInfoIPC.payLoadDescriptor == HSOK)
	{
	    char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int) + 1);
	    InfoIPC sInfoIPC;
	    memset(num_sector_str, '\0', sizeof(char) * sizeof(unsigned int) + 1);
	    sprintf(num_sector_str, "%u", num_sector);
	    sInfoIPC.payLoadLength = strlen(num_sector_str) + 1;
	    generarStructIPC(num_sector_str,READ_SECTOR_REQUEST_LAST,&sInfoIPC);
	    enviarIPC(iSocketConectado ,&sInfoIPC);
	    free(num_sector_str);
	    
	    InfoIPC rInfoIPC;
	    unsigned int nro_pedido, nro_sector;
	    recibirIPC(iSocketConectado,&rInfoIPC);
	    if(rInfoIPC.payLoadDescriptor == NUMEROPEDIDO)
	    {
		nro_pedido = atoi(rInfoIPC.payload);
	    
		recibirIPC(iSocketConectado,&rInfoIPC);
		if(rInfoIPC.payLoadDescriptor == RTA_READ_SECTOR_REQUEST)
		{
		    nro_sector = atoi(rInfoIPC.payload);
		    recibirIPC(iSocketConectado,&rInfoIPC);
		    memcpy(*data_sector, rInfoIPC.payload, rInfoIPC.payLoadLength);
		}
	    }
	}
// 	
	close(iSocketConectado);
	free(rInfoIPC.payload);
	free(num_sector_str);
	
    return 1;
}

// int readSector(FILE* disk, bootRegion *boot, unsigned int num_sector, unsigned int offset, unsigned int size, char **data_sector)
// {
//     char *aux_leer = NULL;
//     aux_leer = (char *) malloc(sizeof(char) * boot->bytes_per_sector);
// //     char *aux_leer[512];
//     
// 
// //     /**CONNECT**/
// // //     t_socket_client *client = sockets_createClient("10.0.2.15",atoi("8000") + 1);
// //     t_socket_client* client = malloc( sizeof(t_socket_client) );
// //     client->socket = malloc( sizeof(t_socket) );
// //     client->socket->desc = socket(AF_INET, SOCK_STREAM, 0);
// //     sockets_setMode(client->socket, SOCKETMODE_BLOCK);
// //     
// //     if (client->socket == NULL){
// // 	    return NULL;
// //     }
// //     sockets_setState(client, SOCKETSTATE_DISCONNECTED);
// //     sockets_connect(client, ipDisco, 9012);
// //     
// //     /**Handshake**/
// //     t_nipc *nipc = (t_nipc *) nipc_create(NIPC_HANDSHAKE);
// //     nipc_setdata(nipc, (char *)strdup("PFS"), strlen("PFS") + 1);
// // 
// //     nipc_send(nipc, client);
// // 
// //     nipc_destroy(nipc);
// //     t_socket_buffer *buffer = (t_socket_buffer *)sockets_recv(client);
// //     nipc = (t_nipc *)nipc_deserializer(buffer, 0);
// //     printf("%s", nipc->payload);
// //     sockets_bufferDestroy(buffer);
// //     nipc_destroy(nipc);
//     
//     if (disk == NULL)
//     {
// 	printf("Error al leer el archivo\n");
// 	return 0;
//     }
//     else
//     {
// 	fseek(disk,(num_sector * boot->bytes_per_sector) + offset,SEEK_SET);
// 	fread(aux_leer, 1, (size - offset), disk);
// 
// // 	t_nipc *nipc2 = (t_nipc *) nipc_create(NIPC_HANDSHAKE);
// // 	nipc2->type = NIPC_READSECTOR_RQ;
// // 	char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int)+ 1);
// // 	sprintf(num_sector_str, "%u", num_sector);
// // 	nipc_setdata(nipc2, num_sector_str, sizeof(char) * sizeof(unsigned int) + 1);
// // 	nipc_send(nipc2, client);
// // 	nipc_destroy(nipc2);
// // 	
// // 	t_nipc *nipc3 = (t_nipc *) nipc_create(NIPC_HANDSHAKE);
// // 	t_socket_buffer *buffer2 = (t_socket_buffer *)sockets_recv(client);
// // 	nipc3 = (t_nipc *)nipc_deserializer(buffer2, 0);
// // 	printf("%s", nipc3->payload);
// // 	memcpy(aux_leer, nipc3->payload + offset, (size - offset));
// // 	sockets_bufferDestroy(buffer2);
// // 	nipc_destroy(nipc3);
// 
//     }  
//     
//     
//     //*data_sector = (char *) malloc(sizeof(char) * boot->bytes_per_sector);
//     *data_sector = aux_leer;
//     
//     
//     return 1;
// }

//Agregar o remover uno o varios clusters libre a una cadena de clusters, Se utiliza libreria generica de list.h
//agregar un cluster addToList(lista, cluster)
//agregar varios cluster addListToList(lista,listaDeCluster)
//eliminar un cluster deleteToList(lista, cluster)
//eliminar varios clusters deleteListToList(lista, listaDeCluster)

int readCluster(FILE* disk, bootRegion* boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
{
    sector *aux_sec = (sector *) malloc(sizeof(sector));
    aux_sec->sec = (char *) malloc(sizeof(char) * boot->bytes_per_sector);
    unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size, i = 0;
        
    div_sectors_int = offset / boot->bytes_per_sector;
    div_sectors_resto = offset % boot->bytes_per_sector;
    
    div_total_size_int = size / boot->bytes_per_sector;
    div_total_size_resto = size % boot->bytes_per_sector;
    
    
    if(div_total_size_int > 0 && div_total_size_resto == 0)
    {
	div_total_size_resto = boot->bytes_per_sector;
	div_total_size_int--;
    }
    
    
    while(i < div_sectors_int)
	i++;
    
    while(i<boot->sectors_per_cluster && i<= div_total_size_int)
//     for(;i<boot->sectors_per_cluster;i++)
    {
	if(i == div_total_size_int)
	    aux_size = div_total_size_resto;
	else
	    aux_size = boot->bytes_per_sector;
	
	readSector(disk, boot, i + (num_cluster * boot->sectors_per_cluster), div_sectors_resto, aux_size, &(aux_sec->sec));
	addToList((gl *)listSectors,aux_sec);
	aux_sec = (sector *) malloc(sizeof(sector));
	aux_sec->sec = (char *) malloc(sizeof(char) * boot->bytes_per_sector);
	div_sectors_resto = 0;
	i++;
    }
    
    free(aux_sec->sec);
    free(aux_sec);
    
    return 1;
}


int addDirectoryInputsFromSector(bootRegion *boot, char *data_sector, directoryInputs *dirs)
{
    int j,z;
    directoryInput *dir = (directoryInput *) malloc(sizeof(directoryInput));
    //char longName[26];
    int longName_flag = 0;
	char *longName16 = (char *) malloc(sizeof(char)*28);
	char *longName8 = (char *) malloc(sizeof(char)*14);
	
    for(j=0;j< boot->bytes_per_sector;j+=32)
    {
	
		if(data_sector[j] == 0)
		{
		    free(longName16);
		    free(longName8);
		    return 0;
		}
		dir = (directoryInput *) malloc(sizeof(directoryInput));
		dir->name = (char *) malloc (sizeof(char) * 14);
		dir->ext = (char *) malloc (sizeof(char) * 4);
		dir->idCluster = 0;
		dir->size = 0;
// 		dir->longName = (char *) malloc(sizeof(char)*14);
		
		//char *aux_idCluster20 = (char *) malloc (sizeof(char));
		//char *aux_idCluster26 = (char *) malloc (sizeof(char));
		int aux_idCluster20 =0;
		int aux_idCluster21 =0;
		int aux_idCluster26 =0;
		int aux_idCluster27 =0;
		int aux_idSize28 =0;
		int aux_idSize29 =0;
		int aux_idSize30 =0;
		int aux_idSize31 =0;
		u_int32_t aux_idCluster = 0, aux_size = 0;
	
		if(data_sector[j] != '\345') //Ã¥ - 0xE5
		{
		    if (data_sector[j+11] == 0x0F)
		    {
// 		
 				
// 	// 		
// 	// // 		El utf16_str_len es el tamaÃ±o de la cadena en utf16. Un ej:
// 	// // 		char cadenaEnUTF16[] = { 'a', '\0', 'l', '\0', 'g', '\0', 'o', '\0', '\0', '\0' };
// 	// // 		int tamaÃ±oDeCadenaEnUTF16 = 10;
// 	// // 		char cadenaEnUTF8[tamaÃ±oDeCadenaEnUTF16/2];
// 	// // 		int tamaÃ±oDeCadenaEnUTF8 = 0;
// 	// // 		unicode_utf16_to_utf8_inbuffer(cadenaEnUTF16, tamaÃ±oDeCadenaEnUTF16, cadenaEnUTF8, &tamaÃ±oDeCadenaEnUTF8);
	 			int n = z;
				for(n=j;n<(32+j);n++)
				{
				    if((n-j) >= 1 && (n-j) < 11)
					memcpy(&(longName16)[n-j-1], &((data_sector)[n]), 1);  
				    if((n-j) >= 14 && (n-j) < 26)
					memcpy(&(longName16)[n-j-14+10], &((data_sector)[n]), 1);  
				    if((n-j) >= 28 && (n-j) < 32)
					memcpy(&(longName16)[n-j-28+22], &((data_sector)[n]), 1);  
				}
			
				
				int lenUTF16 = u_strlen(longName16);
				printf("Largo: %i\n",lenUTF16);
				
				int lenUTF8 = 0;
				unicode_utf16_to_utf8_inbuffer(longName16, (lenUTF16+1)*2, longName8, &lenUTF8);
				printf("Nombre: %s\n",longName8);
				longName_flag =1;
				//free(longName16);
				//free(cadenaEnUTF8);
			}
// 			
	// 
	// 		size_t tamanioDeCadenaEnUTF16 = 26;
	// 		char *cadenaEnUTF8;
	// 		size_t tamanioDeCadenaEnUTF8 = 0;
	// 		//cadenaEnUTF8 = unicode_utf16_to_utf8((const uint16_t *)longName, tamanioDeCadenaEnUTF16, &tamanioDeCadenaEnUTF8);
	// 		
	// 		printf("LongName: %s - %s", cadenaEnUTF8, rtrim(cadenaEnUTF8,' '));
	// 		
	// 		longName_flag = 1;
	// 		
// 		    }
		    else
		    {
			for(z=j;z<(32+j);z++)
			{
				if((z-j) < 8)
				memcpy(&(dir->name)[z-j], &((data_sector)[z]), 1);
				if((z-j) >= 8 && (z-j) < 11)
				memcpy(&(dir->ext)[z-j-8], &((data_sector)[z]), 1);

				if((z-j) == 11)
				memcpy(&(dir->type), &((data_sector)[z]), 1);
				
				if((z-j) == 20)
				memcpy(&(aux_idCluster20), &((data_sector)[z]), 1);
				
				if((z-j) == 21)
				memcpy(&(aux_idCluster21), &((data_sector)[z]), 1);
				
				if((z-j) == 26)
				memcpy(&(aux_idCluster26), &((data_sector)[z]), 1);
				
				if((z-j) == 27)
				memcpy(&(aux_idCluster27), &((data_sector)[z]), 1); 
				
				if((z-j) == 28)
				memcpy(&(aux_idSize28), &((data_sector)[z]), 1);
				
				if((z-j) == 29)
				memcpy(&(aux_idSize29), &((data_sector)[z]), 1);
				
				if((z-j) == 30)
				memcpy(&(aux_idSize30), &((data_sector)[z]), 1);
				
				if((z-j) == 31)
				memcpy(&(aux_idSize31), &((data_sector)[z]), 1); 
				
			}
				strcpy(dir->longName,"");
				if(longName_flag)
				{
					strcpy(dir->longName,longName8);
					longName_flag = 0;
				}
		    
			
			if(strncmp(dir->name,"TRASH",5))
			{
				if (dir->type == 32 || dir->type == 16)
				{
					//dir->idCluster = ((aux_idCluster20)[1]*100+(aux_idCluster20)[0])*100+((aux_idCluster26)[1]*100+(aux_idCluster26)[0]);
				
					aux_idCluster = aux_idCluster + aux_idCluster21;
					aux_idCluster =  aux_idCluster << 24;
					dir->idCluster = dir->idCluster | aux_idCluster;
					
					aux_idCluster =  0;
					aux_idCluster = aux_idCluster + aux_idCluster20;
					aux_idCluster =  aux_idCluster << 16;
					dir->idCluster = dir->idCluster | aux_idCluster;
					aux_idCluster =  0;
					aux_idCluster = aux_idCluster + aux_idCluster27;
					aux_idCluster =  aux_idCluster << 8;
					dir->idCluster = dir->idCluster | aux_idCluster;

					aux_idCluster =  0;
					aux_idCluster = aux_idCluster + aux_idCluster26;
					//aux_idCluster =  aux_idCluster << 24;
					dir->idCluster = dir->idCluster | aux_idCluster;
					
					if(dir->type == 32)
					{
					
					aux_size = aux_size + aux_idSize31;
					aux_size =  aux_size << 24;
					dir->size = dir->size | aux_size;
					
					aux_size =  0;
					aux_size = aux_size + aux_idSize30;
					aux_size =  aux_size << 16;
					dir->size = dir->size | aux_size;
					
					aux_size =  0;
					aux_size = aux_size + aux_idSize29;
					aux_size =  aux_size << 8;
					dir->size = dir->size | aux_size;

					aux_size =  0;
					aux_size = aux_size + aux_idSize28;
					dir->size = dir->size | aux_size;
					
					}
					else
					dir->size = 0;
				}
				else
					dir->idCluster = 0;
				
				
				if(dir->type > 0 && longName_flag == 0)
					addToList((gl *)dirs,dir);
			}
			}
		}
    }
    
    return 1;
}  

int addDirectoryInputsFromCluster(bootRegion* boot, cluster *dirCluster, directoryInputs* dirs)
{
 
    cluster *q = dirCluster; 
    
    while (q != NULL && q->data != NULL && q->data->sec != NULL)
    {
	if(addDirectoryInputsFromSector(boot, (q->data->sec), dirs) == 0)
	    return 0;
	
	q = q->sgt;
    }
    
    return 1;
}

int addDirectoryInputsFromLinkedClusters(FILE* disk, bootRegion* boot, fatRegistry* fatTable, unsigned int cluster_num, directoryInputs* dirs)
{
    enum cluster_state state;
//     unsigned int mask = 0x0fffffff;
    sectors *listSectors;
    unsigned int aux_cluster_num, res = 1;

    do
    {
	listSectors = (sectors *) malloc(sizeof(sectors));
	listSectors->data = NULL;
	listSectors->sgt =NULL;
	
	cluster_num = cluster_num + boot->first_data_cluster  - 2;
// 	readCluster(disk, boot, cluster_num, 0, boot->cluster_size, listSectors);
	readClusterFromCache(disk, boot, "", cluster_num, 0, boot->cluster_size, listSectors);
	res = addDirectoryInputsFromCluster(boot, (cluster *)listSectors, dirs);
	
	cluster_num = cluster_num - boot->first_data_cluster  + 2;
	getClusterState(fatTable, cluster_num, &state, &aux_cluster_num);
	cluster_num = aux_cluster_num;
	
// 	cluster_num = fatTable[cluster_num] & mask;
// 	switch(cluster_num)
// 	{
// 	    case 0x00000000:
// 		state = free_cluster;
// 	    break;
// 	    case 0x00000001:
// 		state = reserved;
// 	    break;
// 	    case 0x0FFFFFF6:
// 		state = reserved;
// 	    break;
// 	    case 0x0FFFFFF7:
// 		state = bad;
// 	    break;
// 	    default:
// 		if(cluster_num >= 0x00000002 && cluster_num <= 0x0FFFFFEF)
// 		{
// 		    state = used;
// 		} else if (cluster_num >= 0x0FFFFFF8 || cluster_num <= 0x0FFFFFFF)
// 		{
// 		    state = last;
// 		} else
// 		    state = error;
// 	    break;
// 	}
	
	
    } while((listSectors!=NULL)&&(state == used)&&(res!=0));
        
    return 1;
}    

int addDirectoryContent(directory *direct,directoryInputs *dirs)
{
    directoryInputs *x = NULL;
    int l = 0;
    x = dirs;
    
    direct->content = (directory *) malloc (sizeof(directory));
//     direct->content->data = (directoryInput *) malloc (sizeof(directoryInput));
    direct->content->data = NULL;
    direct->content->sgt = NULL;
    //direct->sgt = NULL;
    
    while (x != NULL && x->data != NULL)
    {
	if (x->data->type == 32 || x->data->type == 16)
	{
	    directoryInput *data = (directoryInput *) malloc (sizeof(directoryInput));
	    
	    data->name = (char *) malloc (sizeof(char) * 9);
	    strcpy(data->name, x->data->name);
	    data->ext = (char *) malloc (sizeof(char) * 4);
	    strcpy(data->ext, x->data->ext);
	    data->idCluster = x->data->idCluster;
	    data->type = x->data->type;
	    data->size = x->data->size;
// 		data->longName = (char *) malloc (sizeof(char) * 14);
		if(x->data->longName != NULL)
			strcpy(data->longName, x->data->longName);
	    
	    addToListWithSublist((glws *)direct->content, data, NULL);
	} 
	x = x->sgt;
    }   
} 

int addDirectory(FILE* disk, bootRegion* boot, fatRegistry* fatTable, unsigned int cluster_num, directory* direct)
{
    directoryInputs *dirs;
    
//     cluster_num = boot->first_data_cluster + cluster_num - 2;
    
    dirs = (directoryInputs *)malloc(sizeof(directoryInputs));
    dirs->data = NULL;
    dirs->sgt = NULL;
   
    cache_enabled = 0;
    addDirectoryInputsFromLinkedClusters(disk, boot, fatTable, cluster_num, dirs);
    cache_enabled = 1;
    
	if(dirs != NULL && dirs->data != NULL)
		addDirectoryContent(direct, dirs);
	else
		direct->content = NULL;
    
}

int addDirectoryTree(FILE* disk, bootRegion* boot, fatRegistry* fatTable, unsigned int cluster_num, directory* direct, int level)
{
    if (direct != NULL)
    {
	if (level > 0)
	{
	    
	    addDirectory(disk, boot, fatTable, direct->data->idCluster, direct);
	    
	    if ((level - 1) != 0)
	    {
		directory *p = direct->content;
		while (p != NULL)
		{
		    if(p->data->type == 16 && strcmp(p->data->name,".       ") && strcmp(p->data->name,"..      "))
			    addDirectoryTree(disk, boot, fatTable, p->data->idCluster, p, level - 1);
		    
		    p = p->sgt;
		}
	    }
		    
	}
	else 
	{
	    if (level == -1)
	    {
		addDirectory(disk, boot, fatTable, direct->data->idCluster, direct);
		
		directory *p = direct->content;
		while (p != NULL)
		{
		    if(p->data->type == 16 && strcmp(p->data->name,".       ") && strcmp(p->data->name,"..      "))
			    addDirectoryTree(disk, boot, fatTable, p->data->idCluster, p, level);
		    
		    p = p->sgt;
		}   
	    }
	}
	
	return 1;
    }
    else 
	return 0;
    
}

// int searchDirectory(directory *dir, char* name, directory *result)
// {
//     int lenght = 0;
//     directory *p = dir;
//     while (p != NULL)
//     {
// 	lenght = (int)strlen(name);
// 	if(p->data->type == 16 && (!strncmp(p->data->name,name,lenght)))
// 	    result=p;
// 	p = p->sgt;
//     } 
//     return 1;
// }

// int cutPath(const char *path,char *directory[])
// {
//     int i;
//     char *aux = (char *) malloc(sizeof(char) * strlen(path));
//     strcpy(aux,path);
//     directory[0] = strtok(aux,"/");
//     for(i = 1; (directory[i]= strtok(NULL, "/"));i++);
//     
//     free(aux);
//     return 1;
// }

int hotfat_open(const char *path, struct fuse_file_info *fi)
{
//     if(strcmp(path, "/CHELO") != 0)
//         return -ENOENT;
// 
//     if((fi->flags & 3) != O_RDONLY)
//         return -EACCES;

    if(createCacheFile(path, fi->flags))
	return 0;
    else
	return -1;
}

void hotfat_fullpath(char fpath[256], const char *path)
{
    
    strcpy(fpath, "/home/utn_so/prueba/chelo/");
    strncat(fpath, path, 512); // ridiculously long paths will
				    // break here

}


int hotfat_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi)
{
    size_t len;
    (void) fi;
    
    int flag = 0;
    
    if(strncmp(path,"/.Trash",7) != 0 && strcmp(path,"/.hidden") != 0)
	{
        if(strcmp(path, "/") == 0)
		{
// 	    	aux_size = 0;
		}
		else
		{
			directory *q = (directory *) malloc(sizeof(directory));
			searchDirectory(path,root,&q);
			if(q->data->type == 32)
			{
				if(offset > q->data->size)
					size = 0;
				else
					if((size + offset) > q->data->size)
						size = q->data->size - offset;
				
				if(size > 0)
				{
					char *ret_str = (char *) malloc (sizeof(char) * size);
					unsigned int newSize = 0;
					
					readFileFromLinkedClusters(disk, boot, fatTablePointer, path, q->data->idCluster, offset, size, &ret_str, &newSize);
					
					size = newSize;
					memcpy(buf,ret_str,size);
					
				}
				else
					strcpy(buf,"");
			
			}
		}
	}
    else
		strcpy(buf,"");
    
    return size;
    
}

// int readFileFromLinkedClusters(FILE* disk, bootRegion* boot, fatRegistry* fatTable, unsigned int cluster_num, char** content)
int readFileFromLinkedClusters(FILE* disk, bootRegion *boot, fatRegistry *fatTable, const char *path, unsigned int cluster_num, unsigned int offset, unsigned int size, char **content, unsigned int *newSize)
{    
    enum cluster_state state;
    sectors *listSectors = NULL;
    listSectors = (sectors *) malloc(sizeof(sectors));
    listSectors->data = NULL;
    listSectors->sgt = NULL;
    sectors *aux_sector;
    unsigned int first_cluster_num = cluster_num;
    unsigned int aux_cluster_num;
    int aux_size = 0;
    *newSize = 0;
    
    unsigned int div_clusters_int, div_clusters_resto, div_total_size_int, div_total_size_resto;
    unsigned int i = 0;
    
    div_clusters_int = offset / boot->cluster_size;
    div_clusters_resto = offset % boot->cluster_size;
    
    div_total_size_int = size / boot->cluster_size;
    div_total_size_resto = size % boot->cluster_size;
    
//     if(div_total_size_int > 0 && div_total_size_resto == 0)
//     {
// 	div_total_size_resto = boot->cluster_size;
// 	div_total_size_int--;
//     }
    
    state = used;
    
    while(state == used && i < div_clusters_int)
    {
	getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
	
	if(state == used)
	    cluster_num = aux_cluster_num;
	
	i++;
	
    }
    
    if(i == div_clusters_int)
    {

	do
	{
	    
	    if(i == div_total_size_int)
		aux_size = div_total_size_resto;
	    else
		aux_size = boot->cluster_size;
		
	    
// 	    readCluster(disk, boot, cluster_num + boot->first_data_cluster - 2, div_clusters_resto, aux_size, listSectors);
	    readClusterFromCache(disk, boot, path, cluster_num + boot->first_data_cluster - 2, div_clusters_resto, aux_size, listSectors);
	    
	    getClusterState(fatTable, cluster_num, &state, &aux_cluster_num);
	    
	    cluster_num = aux_cluster_num;
	    *newSize = *newSize + (aux_size - div_clusters_resto);
	    div_clusters_resto = 0;
	    i++;

	} while(state == used && i < div_total_size_int);
	    
	
// 	getFileSize(disk, boot, fatTable, first_cluster_num, &aux_size);
	
	aux_sector = listSectors;
	
	char *aux_text = (char *) malloc(sizeof(char) * (*newSize)); //+ 1));
	strcpy(aux_text,"");
// 	while(aux_sector!= NULL)
// 	{
// 	    sprintf(aux_text,"%s%s",aux_text,(aux_sector->data->sec));
// 	    
// 	    aux_sector = aux_sector->sgt;
// 	}	
	
	    
	div_total_size_int = (*newSize) / boot->bytes_per_sector;
	div_total_size_resto = (*newSize) % boot->bytes_per_sector;
	
	if(div_total_size_int > 0 && div_total_size_resto == 0)
	{
	    div_total_size_resto = boot->bytes_per_sector;
	    div_total_size_int--;
	}
    
	unsigned int copied = 0;
	while(aux_sector!= NULL && aux_sector->data != NULL && aux_sector->data->sec != NULL && copied < div_total_size_int)
	{
	    memcpy((aux_text+(copied*boot->bytes_per_sector)), aux_sector->data->sec, boot->bytes_per_sector);
	    
	    aux_sector = aux_sector->sgt;
	    copied++;
	}
	if(aux_sector!= NULL && aux_sector->data != NULL && aux_sector->data->sec != NULL && copied == div_total_size_int)
	{
	    memcpy((aux_text+(copied*boot->bytes_per_sector)), aux_sector->data->sec, div_total_size_resto);
	    aux_sector = aux_sector->sgt;
	}
	
// 	while(listSectors!= NULL)
// 	{
// 	    aux_sector = listSectors;
// 	    listSectors = listSectors->sgt;
// 	}

// 	strcpy(*content, aux_text);
	memcpy(*content, aux_text, *newSize);

    }
    else 
    {
	strcpy(*content, (char *) "");
	return 0;
    }
    
    
    return 1;
    
}


int writeSector(FILE* disk, bootRegion *boot, unsigned int num_sector, unsigned int offset, unsigned int size, char *data_sector)
{

    int iSocketConectado = crearSocket(AF_INET);
    Conectar2(iSocketConectado, ipDisco, puertoDisco);	
    
    InfoIPC rInfoIPC;
    char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int)+ 1);
    
    char *data_send = (char *) malloc(sizeof(char) * size);
    
    rInfoIPC.payLoadLength = 5;
    generarStructIPC("nada",HANDSHAKE,&rInfoIPC);
    enviarIPC(iSocketConectado,&rInfoIPC);
    
    recibirIPC(iSocketConectado,&rInfoIPC);
    if(rInfoIPC.payLoadDescriptor == HSOK)
    {
	sprintf(num_sector_str, "%u", num_sector);
	rInfoIPC.payLoadLength = strlen(num_sector_str) + 1;
	generarStructIPC(num_sector_str,WRITE_SECTOR_REQUEST,&rInfoIPC);
	enviarIPC(iSocketConectado,&rInfoIPC);
	
	recibirIPC(iSocketConectado,&rInfoIPC);
	if(rInfoIPC.payLoadDescriptor == RTA_WRITE_SECTOR_REQUEST)
	{
	    rInfoIPC.payLoadLength = 512;
	    memcpy(data_send, data_sector + offset, size);
	    generarStructIPC(data_send,SET_SECTORES,&rInfoIPC);
	    enviarIPC(iSocketConectado,&rInfoIPC);
	    
	    recibirIPC(iSocketConectado,&rInfoIPC);
	    if(rInfoIPC.payLoadDescriptor != RTA_SET_SECTORES)
	    {
		close(iSocketConectado);
		free(rInfoIPC.payload);
		free(num_sector_str);
		free(data_send);
		return -1;
	    }
	    
	}
	else
	    {
		close(iSocketConectado);
		free(rInfoIPC.payload);
		free(num_sector_str);
		free(data_send);
		return -1;
	    }
	
    }
    
    close(iSocketConectado);
    free(rInfoIPC.payload);
    free(num_sector_str);
    free(data_send);
    
    return 1;
    
//     if (disk == NULL)
//     {
// 	printf("Error al leer el archivo\n");
// 	return 0;
//     }
//     else
//     {
// 	fseek(disk,(num_sector * boot->bytes_per_sector) + offset ,SEEK_SET);
// 	fwrite(data_sector, 1, (size - offset), disk);
//     }  
//     
//     return 1;
}


int writeCluster(FILE* disk, bootRegion* boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
{
    sectors *aux_sec;
    int i;
    unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size;
        
    div_sectors_int = offset / boot->bytes_per_sector;
    div_sectors_resto = offset % boot->bytes_per_sector;
    
    div_total_size_int = size / boot->bytes_per_sector;
    div_total_size_resto = size % boot->bytes_per_sector;
    
    if(div_total_size_int > 0 && div_total_size_resto == 0)
    {
	div_total_size_resto = boot->bytes_per_sector;
	div_total_size_int--;
    }
    
    sectors *q = listSectors;
    
    for(i=0;i< div_sectors_int && q != NULL;i++)
	q = q->sgt;
    
//     for(;i< boot->sectors_per_cluster && q != NULL;i++)
	
    while(i<boot->sectors_per_cluster && i<= div_total_size_int && q != NULL && q->data != NULL && q->data->sec != NULL) 
    {
	if(i == div_total_size_int)
	    aux_size = div_total_size_resto;
	else
	    aux_size = boot->bytes_per_sector;
	
	writeSector(disk, boot, (num_cluster * boot->sectors_per_cluster) + i, div_sectors_resto, aux_size, q->data->sec);
	
	div_sectors_resto = 0;
	q = q->sgt;
	i++;
    }
    
    
//     while(listSectors != NULL && counter <= boot->sectors_per_cluster)
//     {
// 	i = (num_cluster * boot->sectors_per_cluster) + counter;
// 	
// 	writeSector(disk, boot, i, listSectors->data->sec);
// 	
// 	aux_sec = listSectors;
// 	listSectors = listSectors->sgt;
// 	free(aux_sec);
// 	
// 	counter = counter + 1;
//     }
// 	
//     if(q != NULL)
// 	return 0; //Error
//     else
	return 1; //Todo OK!
}



int writeClusterNIPC(FILE* disk, bootRegion* boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
{

    
    sectors *aux_sec;
    int i;
    unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size;
        
    div_sectors_int = offset / boot->bytes_per_sector;
    div_sectors_resto = offset % boot->bytes_per_sector;
    
    div_total_size_int = size / boot->bytes_per_sector;
    div_total_size_resto = size % boot->bytes_per_sector;
    
    if(div_total_size_int > 0 && div_total_size_resto == 0)
    {
	div_total_size_resto = boot->bytes_per_sector;
	div_total_size_int--;
    }
    
    sectors *q = listSectors;
    
    for(i=0;i< div_sectors_int && q != NULL;i++)
	q = q->sgt;
    
    
    int iSocketConectado = crearSocket(AF_INET);
    Conectar2(iSocketConectado, ipDisco, puertoDisco);	
    
    InfoIPC hsInfoIPC;
    
    hsInfoIPC.payLoadLength = 5;
    generarStructIPC("nada",HANDSHAKE,&hsInfoIPC);
    enviarIPC(iSocketConectado,&hsInfoIPC);
    
    recibirIPC(iSocketConectado,&hsInfoIPC);
    if(hsInfoIPC.payLoadDescriptor == HSOK)
    {
	nipcCluster *cluster_data = (nipcCluster *) malloc ((boot->sectors_per_cluster - i) * sizeof(nipcCluster));
	int cant = 0;
	while(i<boot->sectors_per_cluster && i<= div_total_size_int && q != NULL && q->data != NULL && q->data->sec != NULL)
	{
	    if(i == div_total_size_int)
		aux_size = div_total_size_resto;
	    else
		aux_size = boot->bytes_per_sector;
	    
	    cluster_data[cant].sector_num = i + (num_cluster * boot->sectors_per_cluster);
	    cluster_data[cant].offset = div_sectors_resto;
	    cluster_data[cant].size = aux_size;
	    cluster_data[cant].wrote = 0;
	    
	    char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int) + 1);
	    InfoIPC sInfoIPC;
	    memset(num_sector_str, '\0', sizeof(char) * sizeof(unsigned int) + 1);
	    sprintf(num_sector_str, "%u", cluster_data[cant].sector_num);
	    sInfoIPC.payLoadLength = strlen(num_sector_str) + 1;
	    generarStructIPC(num_sector_str,WRITE_SECTOR_REQUEST,&sInfoIPC);
	    enviarIPC(iSocketConectado ,&sInfoIPC);
	    
	    recibirIPC(iSocketConectado,&sInfoIPC);
	    if(sInfoIPC.payLoadDescriptor == RTA_WRITE_SECTOR_REQUEST)
	    {
		sInfoIPC.payLoadLength = aux_size;
		char *data_send = (char *) malloc(sizeof(char) * aux_size);
		memcpy(data_send, q->data->sec + div_sectors_resto, aux_size);
		generarStructIPC(data_send,SET_SECTORES_LAST,&sInfoIPC);
		enviarIPC(iSocketConectado,&sInfoIPC);
		
		cant++;
		free(data_send);
		
	    }
	    else
	    {
		close(iSocketConectado);
		free(cluster_data);
		return -1;
	    }
	    
	    free(num_sector_str);
	    
	    div_sectors_resto = 0;
	    q = q->sgt;
	    i++;
	}
	
	unsigned int max_sock = 0;
	fd_set set_socket;
	FD_SET(iSocketConectado, &set_socket);
	
	struct timeval timeout;
	int rv;
	
	timeout.tv_sec = 3;
	timeout.tv_usec = 0;

	int j=0;
	int w=0;
	int done = 0;
	i=0;
	
	while(w < cant)
	{
	    FD_ZERO(&set_socket);
	    FD_SET(iSocketConectado, &set_socket);
	    
	    rv = select(iSocketConectado+1, &set_socket, NULL, NULL, &timeout);
	    if(rv == -1){
		printf("Llamada del Select error\n");
		FD_CLR(iSocketConectado, &set_socket);
		close(iSocketConectado);
		free(cluster_data);
		return -1;
	    }
	    if(rv == 0)
		break;
	    
	    if(FD_ISSET(iSocketConectado, &set_socket))
	    {
		InfoIPC rInfoIPC;
		unsigned int nro_pedido, nro_sector;
		recibirIPC(iSocketConectado,&rInfoIPC);
		if(rInfoIPC.payLoadDescriptor == NUMEROPEDIDO)
		{
		    nro_pedido = atoi(rInfoIPC.payload);
		
		    recibirIPC(iSocketConectado,&rInfoIPC);
		    if(rInfoIPC.payLoadDescriptor == RTA_WRITE_SECTOR_REQUEST)
		    {
			nro_sector = atoi(rInfoIPC.payload);
			for(j=0;j<cant;j++)
			    if(cluster_data[j].sector_num == nro_sector)
				cluster_data[j].wrote = 1;
			    
			w++;
		    }
		    else
			cluster_data[j].wrote = 4;
		}
		else
		{
		    rv = 0;
		    break;
		}
	    }
	    
	    FD_CLR(iSocketConectado, &set_socket);
	    
	}
	
	close(iSocketConectado);
	
	int retv = 0;
	if(w < cant && rv == 0)
	    retv = writeClusterNIPC(disk, boot, num_cluster, offset, size, listSectors);
	else
	{
	    for(i=0;i<cant;i++)
	    {
		if(cluster_data[j].wrote == 4)
		{
		    free(cluster_data);
		    return -1;
		}
	    }
	    retv = 1;
	}
	free(cluster_data);
	
	return retv;
    }
    else
    {
	close(iSocketConectado);
	return -1;
    }

}


// int writeClusterNIPC(FILE* disk, bootRegion* boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
// {
// 
//     
//     sectors *aux_sec;
//     int i;
//     unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size;
//         
//     div_sectors_int = offset / boot->bytes_per_sector;
//     div_sectors_resto = offset % boot->bytes_per_sector;
//     
//     div_total_size_int = size / boot->bytes_per_sector;
//     div_total_size_resto = size % boot->bytes_per_sector;
//     
//     if(div_total_size_int > 0 && div_total_size_resto == 0)
//     {
// 	div_total_size_resto = boot->bytes_per_sector;
// 	div_total_size_int--;
//     }
//     
//     sectors *q = listSectors;
//     
//     for(i=0;i< div_sectors_int && q != NULL;i++)
// 	q = q->sgt;
//     
//     nipcCluster *cluster_data = (nipcCluster *) malloc ((boot->sectors_per_cluster - i) * sizeof(nipcCluster));
//     int cant = 0;
//     while(i<boot->sectors_per_cluster && i<= div_total_size_int && q != NULL)
//     {
// 	if(i == div_total_size_int)
// 	    aux_size = div_total_size_resto;
// 	else
// 	    aux_size = boot->bytes_per_sector;
// 	
// 	cluster_data[cant].sector_num = i + (num_cluster * boot->sectors_per_cluster);
// 	cluster_data[cant].offset = div_sectors_resto;
// 	cluster_data[cant].size = aux_size;
// 	cluster_data[cant].wrote = 0;
// 
// 	
// // 	int iSocketConectado = crearSocket(AF_INET);
// 	cluster_data[cant].sock_desc = crearSocket(AF_INET);
// 	Conectar2(cluster_data[cant].sock_desc, ipDisco, puertoDisco);	
// 	
// 	InfoIPC hsInfoIPC;
// 	
// 	hsInfoIPC.payLoadLength = 5;
// 	generarStructIPC("nada",HANDSHAKE,&hsInfoIPC);
// 	enviarIPC(cluster_data[cant].sock_desc,&hsInfoIPC);
// 	
// 	recibirIPC(cluster_data[cant].sock_desc,&hsInfoIPC);
// 	if(hsInfoIPC.payLoadDescriptor == HSOK)
// 	{
// // 	    cluster_data[cant].sock_desc = iSocketConectado;
// 	    char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int) + 1);
// 	    InfoIPC sInfoIPC;
// 	    memset(num_sector_str, '\0', sizeof(char) * sizeof(unsigned int) + 1);
// 	    sprintf(num_sector_str, "%u", cluster_data[cant].sector_num);
// 	    sInfoIPC.payLoadLength = strlen(num_sector_str) + 1;
// 	    generarStructIPC(num_sector_str,WRITE_SECTOR_REQUEST,&sInfoIPC);
// 	    enviarIPC(cluster_data[cant].sock_desc ,&sInfoIPC);
// 	    
// 	    recibirIPC(cluster_data[cant].sock_desc,&sInfoIPC);
// 	    if(sInfoIPC.payLoadDescriptor == RTA_WRITE_SECTOR_REQUEST)
// 	    {
// 		sInfoIPC.payLoadLength = aux_size;
// 		char *data_send = (char *) malloc(sizeof(char) * aux_size);
// 		memcpy(data_send, q->data->sec + div_sectors_resto, aux_size);
// 		generarStructIPC(data_send,SET_SECTORES_LAST,&sInfoIPC);
// 		enviarIPC(cluster_data[cant].sock_desc,&sInfoIPC);
// 		
// 		cant++;
// 		free(data_send);
// 		
// 	    }
// 	    else
// 	    {
// 		int counter = 0;
// 		while(counter < cant)
// 		{
// 		    close(cluster_data[counter].sock_desc);
// 		    counter++;
// 		}
// 		free(cluster_data);
// 		return -1;
// 	    }
// 	    
// 	    free(num_sector_str);
// 	}
// 	else
// 	{
// 	    int counter = 0;
// 	    while(counter < cant)
// 	    {
// 		close(cluster_data[counter].sock_desc);
// 		counter++;
// 	    }
// 	    free(cluster_data);
// 	    return -1;
// 	}
// 	
// 	div_sectors_resto = 0;
// 	q = q->sgt;
// 	i++;
//     }
//     
//     int sock_desc = crearSocket(AF_INET);
//     Conectar2(sock_desc, ipDisco, puertoDisco);
//     
//     InfoIPC hsInfoIPC;
//     hsInfoIPC.payLoadLength = 5;
//     generarStructIPC("nada",HANDSHAKE,&hsInfoIPC);
//     enviarIPC(sock_desc,&hsInfoIPC);
//     
//     recibirIPC(sock_desc,&hsInfoIPC);
//     
//     unsigned int max_sock = 0;
//     fd_set set_socket;
//     for(i=0;i<cant;i++)
//     {
// 	if(cluster_data[i].sock_desc > 0)
// 	{
// 	    FD_SET(cluster_data[i].sock_desc, &set_socket);
// 	    if(cluster_data[i].sock_desc > max_sock)
// 		max_sock = cluster_data[i].sock_desc;
// 	}
//     }
//     
//     struct timeval timeout;
//     int rv;
//     
//     timeout.tv_sec = 3;
//     timeout.tv_usec = 0;
// 
//     int j=0;
//     int w=0;
//     int done = 0;
//     i=0;
//     
//     while(w < cant)
//     {
// 	rv = select(max_sock+1, &set_socket, NULL, NULL, &timeout);
// 	if(rv == -1){
// 	    printf("Llamada del Select error\n");
// 	    int counter = 0;
// 	    while(counter < cant)
// 	    {
// 		FD_CLR(cluster_data[counter].sock_desc, &set_socket);
// 		close(cluster_data[counter].sock_desc);
// 		counter++;
// 	    }
// 	    free(cluster_data);
// 	    return -1;
// 	}
// 	if(rv == 0)
// 	    break;
// 	
// 	i=0;
// 	done = 0;
// 	while(i < cant && done == 0)
// 	{
// 	    if(FD_ISSET(cluster_data[i].sock_desc, &set_socket))
// 	    {
// 		InfoIPC rInfoIPC;
// 		recibirIPC(cluster_data[i].sock_desc,&rInfoIPC);
// 		for(j=0;j<cant;j++)
// 		    if(cluster_data[j].sector_num == cluster_data[i].sector_num)
// 			if(rInfoIPC.payLoadDescriptor != RTA_SET_SECTORES)
// 			    cluster_data[j].wrote = 1;
// 			else
// 			    cluster_data[j].wrote = 4; //Error
// 		    
// 		FD_CLR(cluster_data[i].sock_desc, &set_socket);
// 		close(cluster_data[i].sock_desc);
// 		w++;
// 		done = 1;
// 	    }
// 	    i++;
// 	}
//     }
//     
//     close(sock_desc);
//     
//     int retv = 0;
//     if(w < cant && rv == 0)
//     {
// 	int counter = 0;
// 	while(counter < cant)
// 	{
// 	    close(cluster_data[counter].sock_desc);
// 	    counter++;
// 	}
// 	retv = writeClusterNIPC(disk, boot, num_cluster, offset, size, listSectors);
//     }
//     else
//     {
// 	for(i=0;i<cant;i++)
// 	{
// 	    if(cluster_data[j].wrote == 4)
// 	    {
// 		free(cluster_data);
// 		return -1;
// 	    }
// 	}
// 	retv = 1;
//     }
//     free(cluster_data);
//     
//     return retv;
// }




// int getFileSize(FILE* disk, bootRegion* boot, fatRegistry* fatTable, const char *path, unsigned int cluster_num, int* size)
// {    
//     enum cluster_state state;
// //     unsigned int mask = 0x0fffffff;
//     sectors *listSectors = NULL;
//     listSectors = (sectors *) malloc(sizeof(sectors));
//     listSectors->data = NULL;
//     unsigned int aux_cluster_num;
//     int size2 = 0;
//     
//     if(cluster_num > 0)
//     {
// 	
// 	do
// 	{	
// 	    
// 	    getClusterState(fatTable, cluster_num, &state, &aux_cluster_num);
// 	    
// 	    if(state == used)
// 		size2 = size2 + boot->cluster_size;
// 		
// 	    if(state == last)
// 	    {
// // 		readCluster(disk, boot, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
// 		readClusterFromCache(disk, boot, path, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
// 		
// // 		sectors *aux_sector;
// 		
// 		while(listSectors != NULL)
// 		{
// 		    if(listSectors->data != NULL)
// 		    {
// 			if(listSectors->data->sec != NULL)
// 			{
// 			    size2 = size2 + strlen(listSectors->data->sec);
// 			}
// 		    }
// 		    
// 		    listSectors = listSectors->sgt;
// 		}
// 		    
// 	    }
// 	    
// 	    cluster_num = aux_cluster_num;
// 	    
// 	} while(state == used);
//     
//     }
//     else
// 	size2 = 0;
// 	
//     *size = size2;
//     
//     return 1;
//     
// }


int hotfat_truncate(const char *path, off_t offset)
{
 
    int flag = 0, aux_size = 0;
    
    if(strncmp(path,"/.Trash",7) != 0 && strcmp(path,"/.hidden") != 0){
        if(strcmp(path, "/") == 0) {
	    
	}
	else
	{
	    directory *q = (directory *) malloc(sizeof(directory*));
		searchDirectory(path,root,&q);
		    if(q->data->type == 32)
		    {
			
			int div_clusters_int;
			int div_clusters_resto;
			int i = 0, first_time;
			unsigned int aux_cluster_num, cluster_num;
			enum cluster_state state;
			unsigned int free_cluster_num;
			
			cluster_num = q->data->idCluster;
			aux_cluster_num = q->data->idCluster;
			
			aux_size = q->data->size;
			
			if(q->data->idCluster == 0)
			{
			    getFreeCluster(freeClusters, &free_cluster_num);
			    q->data->idCluster = free_cluster_num;
			    setUsedCluster(freeClusters, 0x0FFFFFF8, q->data->idCluster);
			}
		    
		    
			if(offset < aux_size)
			{
			    sectors *listSectors = NULL;
			    listSectors = (sectors *) malloc(sizeof(sectors));
			    listSectors->data = NULL;
			    listSectors->sgt = NULL;
			    
			    i = 0;
			    div_clusters_int = offset / boot->cluster_size;
			    div_clusters_resto = offset % boot->cluster_size;
			    
			    state = used;
			    
			    while(state == used && i < div_clusters_int)
			    {
				getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
				
				if(state == used)
				    cluster_num = aux_cluster_num;
				
				i++;
				
			    }
			
			    if(i == div_clusters_int)
			    {    
				if(div_clusters_resto > 0)
				{
// 					readCluster(disk, boot, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
				    readClusterFromCache(disk, boot, path, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
				    
				    truncateCluster(listSectors, div_clusters_resto);
// 					writeCluster(disk, boot, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
				    writeClusterIntoCache(disk, boot, path, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
				    
				}
				
				first_time = 1;
				
				do
				{
				    getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
				    
				    if(state == used || state == last)
				    {
					if(first_time == 1)
					{
					    fatTablePointer[cluster_num] = 0x0FFFFFF8;
					    first_time = 0;
					}
					else
					    setFreeCluster(freeClusters, cluster_num);
				    }
				    
				    cluster_num = aux_cluster_num;
				    
				} while(state == used);
			    }
			}
			else if(offset > aux_size)
			{
			    
			    i = 0;
			    div_clusters_int = offset / boot->cluster_size;
			    div_clusters_resto = offset % boot->cluster_size;
			    
			    
			    do
			    {
				i++;
				getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
				
				if(state == used)
				    cluster_num = aux_cluster_num;
				
			    } while(state == used && i <= div_clusters_int);
			    
			    
			    if(state == last)
			    {
				i--;
				
				int aux_offset = aux_size - (i * boot->cluster_size);
				int final_byte = boot->cluster_size;
				unsigned int content, free_cluster_num = 0;
				sectors *listSectors = NULL;
				listSectors = (sectors *) malloc(sizeof(sectors));
				listSectors->data = NULL;
				listSectors->sgt = NULL;
				
				
				do
				{
				    if(i == div_clusters_int)
				    {
					final_byte = div_clusters_resto;
					content = 0x0FFFFFF8;
				    }
				    else
				    {
					getFreeCluster(freeClusters, &free_cluster_num);
					content = 0x00000000 + free_cluster_num;
				    }
				    
// 					readCluster(disk, boot, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
				    readClusterFromCache(disk, boot, path, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
				    
				    increaseCluster(listSectors, aux_offset, final_byte);
// 					writeCluster(disk, boot, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
				    writeClusterIntoCache(disk, boot, path, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
				    
				    setUsedCluster(freeClusters, content, cluster_num);
				    
				    listSectors = (sectors *) malloc(sizeof(sectors));
				    listSectors->data = NULL;
				    listSectors->sgt = NULL;
				
				    aux_offset = 0;
				    cluster_num = free_cluster_num;
				    i++;
				    
				} while(i <= div_clusters_int);
				
			    }
			    else
				return -1;
			    
			    
			}
			q->data->size = offset;
			    
			cacheFiles *w = fileDescriptorsTable;
			while(w != NULL && w->data != NULL && strcmp(w->data->path, path))
			    w = w->sgt;
			
			if(w != NULL && w->data != NULL)
			    if(w->data->cant_opens > 0)
				w->data->wrote = w->data->wrote + offset;
			    
		    }
		}
		
    
// 	    saveFAT(disk, boot, fatTablePointer);
	    
	
    }
    
    
    return 0;
}

int truncateCluster(sectors *listSectors, int offset)
{
    int i, div_sectors_int, div_sectors_resto;
    sectors *q = listSectors;
    
    div_sectors_int = offset / boot->bytes_per_sector;
    div_sectors_resto = offset % boot->bytes_per_sector;
    
    for(i=0;i< div_sectors_int && q != NULL;i++)
	q = q->sgt;
    
    for(;i<boot->sectors_per_cluster && q != NULL && q->data != NULL && q->data->sec != NULL;i++)
    {
	truncateSector(&(q->data->sec), div_sectors_resto);
	div_sectors_resto = 0;
	q = q->sgt;
    }
    
    return 1;
}

int truncateSector(char **data_sector, int offset)
{
    memset((*data_sector)+offset, 0,(boot->bytes_per_sector - offset));
    return 1;
}


int increaseCluster(sectors *listSectors, int offset, int final_byte)
{
    int i, div_sectors_int, div_sectors_resto;
    sectors *q = listSectors;
    
    div_sectors_int = offset / boot->bytes_per_sector;
    div_sectors_resto = offset % boot->bytes_per_sector;
    
    for(i=0;i< div_sectors_int && q != NULL;i++)
	q = q->sgt;
    
    while(i<boot->sectors_per_cluster && q != NULL && q->data != NULL && q->data->sec != NULL)
    {
	if((final_byte - (i * boot->bytes_per_sector)) < boot->bytes_per_sector)
	{
	    increaseSector(&(q->data->sec), div_sectors_resto, final_byte - (i * boot->bytes_per_sector));
	    if(final_byte < boot->cluster_size)
		truncateCluster(listSectors, final_byte);
	    return 1;
	}
	else
	    increaseSector(&(q->data->sec), div_sectors_resto, boot->bytes_per_sector);
	
	div_sectors_resto = 0;
	q = q->sgt;
	i++;
    }
    
    return 1;
}

int increaseSector(char **data_sector, int offset, int final_byte)
{
    memset((*data_sector)+offset, '\0',(final_byte - offset));
    return 1;
}


int getClusterState(fatRegistry *fatTable, unsigned int cluster_num, enum cluster_state *state, unsigned int *cluster_registry)
{
    while(clusters_loaded_FAT < cluster_num)
	loadFAT(disk, boot, fatTablePointer);
    
    unsigned int mask = 0x0fffffff;
    *cluster_registry = (int) (fatTable[cluster_num] & mask);

    switch(*cluster_registry)
    {
	case 0x00000000:
	    *state = free_cluster;
	break;
	case 0x00000001:
	    *state = reserved;
	break;
	case 0x0FFFFFF6:
	    *state = reserved;
	break;
	case 0x0FFFFFF7:
	    *state = bad;
	break;
	default:
	    if(*cluster_registry >= 0x00000002 && *cluster_registry <= 0x0FFFFFEF)
	    {
		*state = used;
	    } 
	    else if (*cluster_registry >= 0x0FFFFFF8 || *cluster_registry <= 0x0FFFFFFF)
	    {
		*state = last;
	    } 
	    else
		*state = error;
	break;
    }
    
    return 1;
}

int saveFAT(FILE* disk, bootRegion *boot, fatRegistry *fatTable)
{
    unsigned int last_loaded, num_sector;
    int i;
    
    num_sector = boot->count_sect_reservados;
    
    int iSocketConectado = crearSocket(AF_INET);
    Conectar2(iSocketConectado, ipDisco, puertoDisco);	
    
    InfoIPC rInfoIPC;
    char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int)+ 1);
    
    rInfoIPC.payLoadLength = 5;
    generarStructIPC("nada",HANDSHAKE,&rInfoIPC);
    
    enviarIPC(iSocketConectado,&rInfoIPC);
    
    recibirIPC(iSocketConectado,&rInfoIPC);
    if(rInfoIPC.payLoadDescriptor == HSOK)
    {
	last_loaded = 0;
	for (i = 0;i< boot->fat32_size;i++)
	{
	    writeSectorFromFAT(disk, boot, num_sector + i, fatTable, last_loaded, iSocketConectado);
	    last_loaded += (boot->bytes_per_sector/4);
	}
    }
    
    int m;
    for(m=0;m<boot->count_clusters_fat;m++)
	modifyPointer[m]=0;
    
    close(iSocketConectado);
	
    
    return 1;
}

int writeSectorFromFAT(FILE* disk, bootRegion *boot, unsigned int num_sector, fatRegistry *fatTable, unsigned int last_loaded, int iSocketConectado)
{
    
    int i, j, modified = 0;
    
    for(i=0,j=last_loaded;i< boot->bytes_per_sector && modified == 0;i+=4,j++)
	if(modifyPointer[j] == 1)
	    modified = 1;
    
    if(modified == 1)
    {
	char *data_sector = (char *) malloc (sizeof(char) * boot->bytes_per_sector);
	
	for(i=0,j=last_loaded;i< boot->bytes_per_sector;i+=4,j++)
	    memcpy(&data_sector[i],&fatTable[j],4);
	
	//Imprimo las dos FATTable
	writeSectorFAT(disk, boot, num_sector, 0, boot->bytes_per_sector, data_sector, iSocketConectado);
	writeSectorFAT(disk, boot, num_sector+ boot->fat32_size, 0, boot->bytes_per_sector, data_sector, iSocketConectado);

	free(data_sector);
    }
    
    return 1;
}

int setFreeCluster(char* freeClusters, unsigned int cluster_num)
{
    
    while(clusters_loaded_FAT < cluster_num)
	loadFAT(disk, boot, fatTablePointer);
    
    clusterIds *aux_list = (clusterIds *) malloc (sizeof(clusterIds));
    aux_list->data = (clusterId *) malloc (sizeof(clusterId));
    
    fatTablePointer[cluster_num] = 0x00000000;
    modifyPointer[cluster_num] = 1;
    
    *(aux_list->data) = cluster_num;
    aux_list->sgt = NULL;
    addFreeClusters(freeClusters, aux_list);
    
    free(aux_list->data);
    free(aux_list);
    
    return 1;
}

int getFreeCluster(char* freeClusters, unsigned int *cluster_num)
{
    
    int i = 0;
    
    if(freeClusters != NULL)
    {
	
	while(i < boot->count_clusters_fat)
	{
	    if(i < clusters_loaded_FAT)
	    {
		if(freeClusters[i] == '0')
		{
		    *cluster_num = i;
		    return 1;
		}
		    
		i++;
	    }
	    else
		loadFAT(disk, boot, fatTablePointer);
	}
    }
    
    
    *cluster_num = -1;
    return 0;
}

int setUsedCluster(char *freeClusters, unsigned int content, unsigned int cluster_num)
{
    while(clusters_loaded_FAT < cluster_num)
	loadFAT(disk, boot, fatTablePointer);
    
    clusterIds *aux_list = (clusterIds *) malloc (sizeof(clusterIds));
    aux_list->data = (clusterId *) malloc (sizeof(clusterId));
    
    fatTablePointer[cluster_num] = content;
    modifyPointer[cluster_num] = 1;
    
    *(aux_list->data) = cluster_num;
    aux_list->sgt = NULL;
    deleteFreeClusters(freeClusters, aux_list);
    
    free(aux_list->data);
    free(aux_list);
    
    return 1;
}


int fillWithChar(char **string, char fill_char, int total_size)
{
    int i = 0;
    
    while((i< total_size) && ((*string)[i] != '\0'))
	i++;
    
    for( ;i < total_size; i++)
	(*string)[i] = fill_char;
    
    return 1;
}

int hotfat_create(const char *path, mode_t mode, struct fuse_file_info *fi)
{
    //Buscar dir padre
    char *pathFather = (char *) malloc(sizeof(char)*256);
	fatherName(path,pathFather);
	
	
    directory *q = (directory *) malloc(sizeof(directory));
    searchDirectory(pathFather,root,&q);
//     root->data = (directoryInput *) malloc (sizeof(directoryInput));
//     root->data->name = (char *) malloc (sizeof(char) * 14); //sizeof(char));
    
    directoryInput *new_input = (directoryInput *) malloc (sizeof(directoryInput));
    new_input->name = (char *) malloc (sizeof(char) * 9);
    new_input->ext = (char *) malloc (sizeof(char) * 4);
    char *name = (char *) malloc (sizeof(char) * 9);
    if(strchr(path,'.') != NULL)
    {
		char *aux_path = (char *) malloc (sizeof(char) * strlen(path));
		newName(path, aux_path);
		strcpy(name, strtok(aux_path,"."));
		strcpy(new_input->ext, strtok(NULL,"\n\0"));
    }
    else
    {
		char *name = (char *) malloc (sizeof(char) * 9);
		newName(path,name);
		strcpy(new_input->ext, "   ");
    }
    
	if(strlen(name)<8)
	{
		strcpy(new_input->name,name);
		strcpy(new_input->longName,"");
	}
	else
	{
		strncpy(new_input->name,name,8);
		strcpy(new_input->longName,name);
	}
    
    
    
    new_input->idCluster = 0;
    new_input->size = 0;
    new_input->type = 32;
    
    char *aux_direct = (char *) malloc(sizeof(char) * 32+1);
	char *aux_longDirect = (char *) malloc(sizeof(char) * 32+1);
    createDirectoryInput(&aux_direct, new_input);
	if(strcmp(new_input->longName,""))
		createLongNameInput(&aux_longDirect,new_input);
		
	saveDirectoryInputIntoLinkedClusters(q->data->idCluster, aux_longDirect, 1);
    if(saveDirectoryInputIntoLinkedClusters(q->data->idCluster, aux_direct, 1))
    {
		if(q->content == NULL)
		{
			q->content = (directory *) malloc(sizeof(directory));
			q->content->data = NULL;
			q->content->content = NULL;
			q->content->sgt = NULL;
		}
		addToListWithSublist((glws *)q->content, new_input, NULL);
		hotfat_open(path,fi);
		free(aux_direct);
		free(aux_longDirect);
		return 0;
    }
    else
    {
	free(aux_direct);
	free(aux_longDirect);
	return -1;
    }
    
    return -1;
}

// int hotfat_mknod(const char *path, mode_t mode , dev_t dev)
// {
//     
//     return 0;
// }

int createDirectoryInput(char **data_dir32, directoryInput *dir)
{
//   uint8_t name[8];
//   uint8_t ext[3];
//   uint8_t type;
//   uint64_t ocho_ceros;
//   uint16_t high_first_cluster;
//   uint32_t cuatro_ceros;
//   uint16_t low_first_cluster;
//   uint32_t size;
    
    
    directoryInputRegistry *aux_data_dir32 = (directoryInputRegistry *) malloc (sizeof(directoryInputRegistry));
    memset(aux_data_dir32, 0, sizeof(directoryInputRegistry));
    
    char *aux_name = (char *) malloc(sizeof(char) * 9);
    char *aux_ext = (char *) malloc(sizeof(char) * 4);
    
    strcpy(aux_name, dir->name);
    fillWithChar(&aux_name, ' ', 8);
    memcpy(aux_data_dir32->name, aux_name, 8);
    
    strcpy(aux_ext, dir->ext);
    fillWithChar(&aux_ext, ' ', 3);
    memcpy(aux_data_dir32->ext, aux_ext, 3);
    
    aux_data_dir32->type = (uint8_t) dir->type;
    aux_data_dir32->low_first_cluster = dir->idCluster & 0x0000FFFF;
    aux_data_dir32->high_first_cluster = dir->idCluster >> 8;
    
    uint32_t aux_size = 0;
    uint8_t aux_idSize[4];
    
    memcpy(&aux_idSize, &(dir->size), sizeof(uint32_t));
    
    aux_size = aux_size + aux_idSize[0];
    aux_data_dir32->size = aux_data_dir32->size | aux_size;
    
    aux_size =  0;
    aux_size = aux_size + aux_idSize[1];
    aux_size =  aux_size << 8;
    aux_data_dir32->size = aux_data_dir32->size | aux_size;
    
    aux_size =  0;
    aux_size = aux_size + aux_idSize[2];
    aux_size =  aux_size << 16;
    aux_data_dir32->size = aux_data_dir32->size | aux_size;

    aux_size =  0;
    aux_size = aux_size + aux_idSize[3];
    aux_size =  aux_size << 24;
    aux_data_dir32->size = aux_data_dir32->size | aux_size;
    
    
    memcpy((*data_dir32), aux_data_dir32, sizeof(directoryInputRegistry));
    sprintf(*data_dir32,"%s\n",*data_dir32);
    
    return 1;
}

int createLongNameInput(char **data_dir32, directoryInput *dir)
{
	char *entryDir = (char *) malloc(sizeof(char)*14);
	char *auxUTF8 = (char *) malloc(sizeof(char)*14);
	char *auxUTF16 = (char *) malloc(sizeof(char)*28);
	int len16;
	strcpy(entryDir,dir->longName);	
	int lenName = strlen(entryDir);
	memset((*data_dir32),' ',32);	
	
	*(*data_dir32) = 'A';
	
	if(lenName>0)
	{
		memset(auxUTF8,'\0',14);
		memset(auxUTF16,'\0',28);
		strncpy(auxUTF8,entryDir,5);
		len16 = 0;
		unicode_utf8_to_utf16_inbuffer(auxUTF8,strlen(auxUTF8),auxUTF16,&len16);
		memcpy((*data_dir32)+1,auxUTF16,len16*2);
	}
	
	*((*data_dir32)+11) = 0xF;	
	*((*data_dir32)+12) = 0x0;
	*((*data_dir32)+13) = 0x0;

	if(lenName>5)
	{
		memset(auxUTF8,'\0',14);
		memset(auxUTF16,'\0',28);		
		strncpy(auxUTF8,entryDir+5,6);
		len16 = 0;
		unicode_utf8_to_utf16_inbuffer(auxUTF8,strlen(auxUTF8),auxUTF16,&len16);
		memcpy((*data_dir32)+14,auxUTF16,len16*2);
	}

	*((*data_dir32)+26) = 0x0;
	*((*data_dir32)+27) = 000;

	if(lenName>11)
	{
		memset(auxUTF8,'\0',14);
		memset(auxUTF16,'\0',28);		
		strncpy(auxUTF8,entryDir+11,2);
		len16 = 0;
		unicode_utf8_to_utf16_inbuffer(auxUTF8,strlen(auxUTF8),auxUTF16,&len16);
		memcpy((*data_dir32)+28,auxUTF16,len16*2);
	}
	
    return 1;
}

int writeFileFromLinkedClusters(FILE *disk, bootRegion *boot, const char *path, fatRegistry *fatTable, unsigned int cluster_num, unsigned int offset, unsigned int size, const char *content, unsigned int *wrote)
{    
    
    unsigned int total_clusters_int, total_clusters_mod, aux_offset_int, aux_offset_mod, aux_size;
    enum cluster_state state;
    unsigned int aux_cluster_num, free_cluster_num, registry;
    
    sectors *listSectors = NULL;
    listSectors = (sectors *) malloc(sizeof(sectors));
    listSectors->data = NULL;
    listSectors->sgt = NULL;
    
    *wrote = 0;
    
    aux_offset_int = offset / boot->cluster_size;
    aux_offset_mod = offset % boot->cluster_size;
    total_clusters_int = (size + offset) / boot->cluster_size;
    total_clusters_mod = (size + offset) % boot->cluster_size;
    
    if(total_clusters_int > 0 && total_clusters_mod == 0)
    {
	total_clusters_mod = boot->cluster_size;
	total_clusters_int--;
    }
    
    int i = 0;
    if(aux_offset_int == 0)
	state = last;
    else
	state = used;
    
    while(state == used && i < aux_offset_int)
    {
	getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
	
	if(state == used)
	    cluster_num = aux_cluster_num;
	
	i++;
	
    }
    
    //Si de una llega un offset mayor al tamaÃ±o del archivo, tengo que aumentar la cantidad de clusters y llenar todo con ceros
    while(state == last && i < aux_offset_int)
    {
	getFreeCluster(freeClusters, &free_cluster_num);
	setUsedCluster(freeClusters, 0x00000000 + free_cluster_num, cluster_num);
	cluster_num = free_cluster_num;
	
	createNullCluster(&(listSectors));
	truncateCluster(listSectors, 0);
	
	writeClusterIntoCache(disk, boot, path, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
	*wrote = *wrote + boot->cluster_size;
	
	setUsedCluster(freeClusters, 0x0FFFFFF8, cluster_num);
	
	getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
	
	listSectors = (sectors *) malloc(sizeof(sectors));
	listSectors->data = NULL;
	listSectors->sgt = NULL;
    }
    
    if (state == last && aux_offset_int > 0)
    {
	getFreeCluster(freeClusters, &free_cluster_num);
	setUsedCluster(freeClusters, 0x00000000 + free_cluster_num, cluster_num);
	cluster_num = free_cluster_num;
	setUsedCluster(freeClusters, 0x0FFFFFF8, cluster_num);
    }

    
    if(i == aux_offset_int)
    { 
	while(i <= total_clusters_int)
	{
	    getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
	    
	    if (state == last)
	    {
		if(i == total_clusters_int)
		    registry = 0x0FFFFFF8;
		else 
		{
		    getFreeCluster(freeClusters, &free_cluster_num);
		    registry = 0x00000000 + free_cluster_num;
		}
	    }
	    
	    
	    if(i == total_clusters_int)
		aux_size = total_clusters_mod;
	    else 
		aux_size = boot->cluster_size;
	    
	    char *aux_content = (char *) malloc(sizeof(char) * aux_size);
// 	    strncpy(aux_content, content, aux_size);
	    memcpy(aux_content, content, aux_size);
	    charToListSectors(aux_content, aux_offset_mod, aux_size, &listSectors);

	    if (state == last)
	    {
		setUsedCluster(freeClusters, registry, cluster_num);
		if(i != total_clusters_int)
		    cluster_num = free_cluster_num;
	    }
	    
// 	    writeCluster(disk, boot, cluster_num + aux_offset_int  + boot->first_data_cluster - 2, aux_offset_mod, aux_size, listSectors);
// 	    writeCluster(disk, boot, cluster_num + boot->first_data_cluster - 2, aux_offset_mod, aux_size, listSectors);
	    writeClusterIntoCache(disk, boot, path, cluster_num + boot->first_data_cluster - 2, aux_offset_mod, aux_size, listSectors);
	    *wrote = *wrote + (aux_size - aux_offset_mod);
	    
	    listSectors = (sectors *) malloc(sizeof(sectors));
	    listSectors->data = NULL;
	    listSectors->sgt = NULL;
	
	    aux_offset_mod = 0;
	    i++;
	    
	}
	
    }
    else
	return -ENOENT;
    
    return 1;

}


int hotfat_write(const char* path, const char* buf, size_t size, off_t offset, struct fuse_file_info* fi)
{
    size_t len;
    (void) fi;
    
    int flag = 0;
    unsigned int wrote = 0;
    
	if(strncmp(path,"/.Trash",7) != 0 && strcmp(path,"/.hidden") != 0)
	{
        if(strcmp(path, "/") == 0) {
// 	    aux_size = 0;
		}
		else
		{
			directory *q = (directory *) malloc(sizeof(directory));
			searchDirectory(path,root,&q);
			unsigned int free_cluster_num;
			if(q->data->type == 32)
			{
				if(size > 0)
				{
					if(q->data->idCluster == 0)
					{
					getFreeCluster(freeClusters, &free_cluster_num);
					q->data->idCluster = free_cluster_num;
					setUsedCluster(freeClusters, 0x0FFFFFF8, q->data->idCluster);
					}
					
					writeFileFromLinkedClusters(disk, boot, path, fatTablePointer, q->data->idCluster, offset, size, buf, &wrote);
					
					if((offset + size) > q->data->size)
					q->data->size = offset + size;
					
					cacheFiles *w = fileDescriptorsTable;
					while(w != NULL && w->data != NULL && strcmp(w->data->path, path))
					w = w->sgt;
					
					if(w != NULL && w->data != NULL)
					{
						if(w->data->cant_opens > 0)
						{
		// 				    if(offset == 0) //Se cambio la forma de verificar si es el primer ingreso
		// 					pthread_mutex_lock(&(w->data->write_mutex));
		// 					sem_wait(&(w->data->write_semaphore));
							
		// 				    w->data->wrote = w->data->wrote + wrote;
							w->data->wrote = wrote + offset;
							
						}
					}
					
// 					saveFAT(disk, boot, fatTablePointer);
				}
			}
		}
    }
    
    return size;
    
}


int charToListSectors(char *buf, unsigned int offset, unsigned int size, sectors **listSectors)
{
    sector *aux_sec;
    aux_sec = (sector *) malloc(sizeof(sector));
    aux_sec->sec = (char *) malloc (sizeof(char) * boot->bytes_per_sector);
    unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size, i = 0, wrote = 0;
        
    div_sectors_int = offset / boot->bytes_per_sector;
    div_sectors_resto = offset % boot->bytes_per_sector;
    
    div_total_size_int = size / boot->bytes_per_sector;
    div_total_size_resto = size % boot->bytes_per_sector;
    
    if(div_total_size_int > 0 && div_total_size_resto == 0)
    {
	div_total_size_resto = boot->bytes_per_sector;
	div_total_size_int--;
    }
    
    while(i < div_sectors_int)
    {
	aux_sec = (sector *) malloc(sizeof(sector));
	aux_sec->sec = (char *) malloc (sizeof(char) * boot->bytes_per_sector);
	increaseSector(&(aux_sec->sec), 0, boot->bytes_per_sector);
	addToList((gl *)(*listSectors),aux_sec);
	i++;
    }
    
    while(i<boot->sectors_per_cluster && i<= div_total_size_int)
    {
	aux_sec = (sector *) malloc(sizeof(sector));
	aux_sec->sec = (char *) malloc (sizeof(char) * boot->bytes_per_sector);
	
	if(i == div_total_size_int)
	    aux_size = div_total_size_resto;
	else
	    aux_size = boot->bytes_per_sector;
	
	if(div_sectors_resto > 0)
	    increaseSector(&(aux_sec->sec), 0, div_sectors_resto);
	
	memcpy((aux_sec->sec),(buf+wrote),aux_size-div_sectors_resto);
	
	if(aux_size < boot->bytes_per_sector)
	    truncateSector(&(aux_sec->sec), aux_size);
// 	    increaseSector(&(aux_sec->sec), aux_size, boot->bytes_per_sector);
	
// 	fillWithChar(&(aux_sec->sec), ' ', boot->bytes_per_sector);
	
	addToList((gl *)(*listSectors),aux_sec);
	
 	wrote = wrote + aux_size - div_sectors_resto;
	
	div_sectors_resto = 0;
	i++;
    }
    
    
    while(i<boot->sectors_per_cluster)
    {
	aux_sec = (sector *) malloc(sizeof(sector));
	aux_sec->sec = (char *) malloc (sizeof(char) * boot->bytes_per_sector);
	
// 	increaseSector(&(aux_sec->sec), 0, boot->bytes_per_sector);
	truncateSector(&(aux_sec->sec), 0);
	addToList((gl *)(*listSectors),aux_sec);
	i++;
    }
    
    
    return 1;
}


int createCacheFile(const char *path, int fi_flags)
{

    cacheFile *file;
    cacheFiles *q = fileDescriptorsTable;
    
    while(q != NULL && q->data != NULL && strcmp(q->data->path, path))
		q = q->sgt;
    
    if(q != NULL && q->data != NULL)
    {
	q->data->cant_opens = q->data->cant_opens + 1;
	
	if ((fi_flags & O_WRONLY) == O_WRONLY || (fi_flags & O_RDWR) == O_RDWR)
	    pthread_mutex_lock(&(q->data->write_mutex)); //Si se abre para write, blockeo el mutex
	
	return 1;
    }
    else
    {
	file = (cacheFile *) malloc (sizeof(cacheFile));
        
// 	if( sem_init( &file->write_semaphore, 0, 1) == -1 ){
//                 free(file);
//                 return NULL;
//         }
        
//         file->write_mutex = ;
// 	pthread_mutex_t a;
// 	file->write_mutex = a;//PTHREAD_MUTEX_INITIALIZER;
	pthread_mutex_init(&(file->write_mutex), NULL);
	
	file->path = (char *) malloc (sizeof(char) * 256);
	strcpy(file->path,path);
	file->cant_opens = 1;
	file->wrote = -1;
	
	int i;
	if(cache_enabled > 0)
	{
	    file->cache = (cacheCluster *) malloc (cant_cache_clusters * sizeof(cacheCluster));
	    for(i=0;i<cant_cache_clusters;i++)
	    {
		file->cache[i].cluster_data = (cluster *) malloc (sizeof(cluster));
		file->cache[i].cluster_data->data = NULL;
		file->cache[i].cluster_data->sgt = NULL;
		file->cache[i].cluster_num = 0;
	    }
	}     
	
        addToList((gl *)fileDescriptorsTable,file);
	
	if ((fi_flags & O_WRONLY) == O_WRONLY || (fi_flags & O_RDWR) == O_RDWR)
	    pthread_mutex_lock(&(file->write_mutex));//Si se abre para write, blockeo el mutex
    }
    
    return 1;
}


// int readClusterFromCache(FILE* disk, bootRegion* boot, const char *path, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
// {
//     if(cache_enabled)
//     {
// 	unsigned int cache_pos, read = 0;
// 	
// 	for(cache_pos = 0; cache_pos < cant_cache_clusters && read == 0; cache_pos++)
// 	{
// 	    if(cache[cache_pos].cluster_num == num_cluster)
// 	    {
// 		//Leo el cluster que necesito de la cache
// 		readCacheCluster(cache_pos, offset, size, listSectors);
// 		read = 1;
// 	    }
// 	}
// 	
// 	if(read == 0)
// 	{
// 	    cache_pos = 0;
// 	    //getLRUCache(cache_pos);
// 	    cache_pos = rand() % cant_cache_clusters;
// 	    //Hago flush() del que voy a sobreescribir
// 	    if(cache[cache_pos].cluster_data->data != NULL)
// 	    {
// 		if(cache[cache_pos].cluster_num != 0)
// 		{
// 		    writeClusterNIPC(disk, boot, cache[cache_pos].cluster_num, offset, size, cache[cache_pos].cluster_data);
// 		    //Limpio el registro de cache
// 		    truncateCluster(cache[cache_pos].cluster_data, 0);
// 		}
// 	    }
// 	    else
// 		createNullCluster(&(cache[cache_pos].cluster_data));
// 	    
// 	
// 	    sectors *auxListSectors = NULL;
// 	    auxListSectors = (sectors *) malloc(sizeof(sectors));
// 	    auxListSectors->data = NULL;
// 	    auxListSectors->sgt = NULL;
// 	    //Traigo el cluster que necesito
// 	    readClusterNIPC(disk, boot, num_cluster, 0, boot->cluster_size, auxListSectors);
// 	    //Lo guardo
// 	    writeCacheCluster(cache_pos, path, num_cluster, 0, boot->cluster_size, auxListSectors);
// 		
// 	    //Si el read es sobre una porcion del cluster, lo traigo entero
// // 	    if(offset == 0 && size == boot->cluster_size)
// // 	    {
// // 		listSectors = auxListSectors;
// // 	    }
// // 	    else
// 	    //Leo el cluster en cuestion de la cache
// 	    readCacheCluster(cache_pos, offset, size, listSectors);
// 		
// 	}
//     }
//     else	
// 	readClusterNIPC(disk, boot, num_cluster, offset, size, listSectors);
//     
// 
//     return 1;
// }
int readClusterFromCache(FILE* disk, bootRegion* boot, const char *path, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
{
    if(cache_enabled)
    {
    
    /*NL*/
				cacheFiles *cf = fileDescriptorsTable;
		    
		    while(cf != NULL && cf->data != NULL && strcmp(cf->data->path, path))
						cf = cf->sgt;
		    
		    if(cf != NULL && cf->data != NULL)
		    {
    
    
	unsigned int cache_pos, read = 0;
	
	for(cache_pos = 0; cache_pos < cant_cache_clusters && read == 0; cache_pos++)
	{
	    if(cf->data->cache[cache_pos].cluster_num == num_cluster)
	    {
		//Leo el cluster que necesito de la cache
		readCacheCluster(cf->data->cache[cache_pos].cluster_data, offset, size, listSectors);
		read = 1;
	    }
	}
	
	if(read == 0)
	{
	    cache_pos = 0;
	    //getLRUCache(cache_pos);
	    cache_pos = rand() % cant_cache_clusters;
	    //Hago flush() del que voy a sobreescribir
	    if(cf->data->cache[cache_pos].cluster_data->data != NULL)
	    {
		if(cf->data->cache[cache_pos].cluster_num != 0)
		{
		    writeClusterNIPC(disk, boot, cf->data->cache[cache_pos].cluster_num, offset, size, cf->data->cache[cache_pos].cluster_data);
		    //Limpio el registro de cache
		    truncateCluster(cf->data->cache[cache_pos].cluster_data, 0);
		}
	    }
	    else
		createNullCluster(&(cf->data->cache[cache_pos].cluster_data));
	    
	
	    sectors *auxListSectors = NULL;
	    auxListSectors = (sectors *) malloc(sizeof(sectors));
	    auxListSectors->data = NULL;
	    auxListSectors->sgt = NULL;
	    //Traigo el cluster que necesito
	    readClusterNIPC(disk, boot, num_cluster, 0, boot->cluster_size, auxListSectors);
	    //Lo guardo
	    cf->data->cache[cache_pos].cluster_num = num_cluster;
	    writeCacheCluster(&(cf->data->cache[cache_pos].cluster_data), path, num_cluster, 0, boot->cluster_size, auxListSectors);
		
	    //Si el read es sobre una porcion del cluster, lo traigo entero
// 	    if(offset == 0 && size == boot->cluster_size)
// 	    {
// 		listSectors = auxListSectors;
// 	    }
// 	    else
	    //Leo el cluster en cuestion de la cache
	    readCacheCluster(cf->data->cache[cache_pos].cluster_data, offset, size, listSectors);
       
    }
    else	
	readClusterNIPC(disk, boot, num_cluster, offset, size, listSectors);
		
	}
    }
    else	
	readClusterNIPC(disk, boot, num_cluster, offset, size, listSectors);
    

    return 1;
}



// int readCacheCluster(unsigned int cache_pos, unsigned int offset, unsigned int size, sectors* listSectors)
// {
//     
//     sector *aux_sec = (sector *) malloc(sizeof(sector));
//     unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size, i = 0;
//         
//     div_sectors_int = offset / boot->bytes_per_sector;
//     div_sectors_resto = offset % boot->bytes_per_sector;
//     
//     div_total_size_int = size / boot->bytes_per_sector;
//     div_total_size_resto = size % boot->bytes_per_sector;
//     
//     if(div_total_size_int > 0 && div_total_size_resto == 0)
//     {
// 	div_total_size_resto = boot->bytes_per_sector;
// 	div_total_size_int--;
//     }
//     
//     cluster *q = cache[cache_pos].cluster_data;
//     
//     while(i < div_sectors_int)
// 	q = q->sgt;
// 	
//     while(i<boot->sectors_per_cluster && i<= div_total_size_int)
//     {
// 	if(i == div_total_size_int)
// 	    aux_size = div_total_size_resto;
// 	else
// 	    aux_size = boot->bytes_per_sector;
// 	
// 	aux_sec->sec = (char *) malloc (sizeof(char) * (aux_size - div_sectors_resto));
// // 	strncpy(aux_sec->sec, q->data->sec + div_sectors_resto,aux_size);
// 	memcpy((aux_sec->sec),(q->data->sec+div_sectors_resto),aux_size-div_sectors_resto);
// 	
// 	addToList((gl *)listSectors,aux_sec);
// 	aux_sec = (sector *) malloc(sizeof(sector));
// 	div_sectors_resto = 0;
// 	q = q->sgt;
// 	i++;
//     }
//     
//     listSectors = cache[cache_pos].cluster_data;
//     
//     return 1;
// }

int readCacheCluster(cluster *cluster_data, unsigned int offset, unsigned int size, sectors* listSectors)
{
    /*NL*/
    sector *aux_sec = (sector *) malloc(sizeof(sector));
    unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size, i = 0;
        
    div_sectors_int = offset / boot->bytes_per_sector;
    div_sectors_resto = offset % boot->bytes_per_sector;
    
    div_total_size_int = size / boot->bytes_per_sector;
    div_total_size_resto = size % boot->bytes_per_sector;
    
    if(div_total_size_int > 0 && div_total_size_resto == 0)
    {
	div_total_size_resto = boot->bytes_per_sector;
	div_total_size_int--;
    }
    
    //cluster *q = cache[cache_pos].cluster_data;
    cluster *q = cluster_data;
    
    while(i < div_sectors_int)
	q = q->sgt;
	
    while(i<boot->sectors_per_cluster && i<= div_total_size_int)
    {
	if(i == div_total_size_int)
	    aux_size = div_total_size_resto;
	else
	    aux_size = boot->bytes_per_sector;
	
	aux_sec->sec = (char *) malloc (sizeof(char) * (aux_size - div_sectors_resto));
// 	strncpy(aux_sec->sec, q->data->sec + div_sectors_resto,aux_size);
	memcpy((aux_sec->sec),(q->data->sec+div_sectors_resto),aux_size-div_sectors_resto);
	
	addToList((gl *)listSectors,aux_sec);
	aux_sec = (sector *) malloc(sizeof(sector));
	div_sectors_resto = 0;
	q = q->sgt;
	i++;
    }
    
    //listSectors = cache[cache_pos].cluster_data;
    listSectors = cluster_data;
    
    return 1;
}
// int writeClusterIntoCache(FILE* disk, bootRegion* boot, const char *path, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
// {
//     if(cache_enabled)
//     {
// 	unsigned int cache_pos, wrote = 0;
// 	
// 	for(cache_pos = 0; cache_pos < cant_cache_clusters && wrote == 0; cache_pos++)
// 	{
// 	    if(cache[cache_pos].cluster_num == num_cluster)
// 	    {
// 		writeCacheCluster(cache_pos, path, num_cluster, offset, size, listSectors);
// 		wrote = 1;
// 	    }
// 	}
// 	
// 	if(wrote == 0)
// 	{
// 	    cache_pos = 0;
// 	    //getLRUCache(cache_pos);
// 	    cache_pos = rand() % cant_cache_clusters;
// 	    //Hago flush() del que voy a sobreescribir
// 	    if(cache[cache_pos].cluster_data->data != NULL)
// 	    {
// 		if(cache[cache_pos].cluster_num != 0)
// 		{
// 		    writeClusterNIPC(disk, boot, cache[cache_pos].cluster_num, offset, size, cache[cache_pos].cluster_data);
// 		    //Limpio el registro de cache
// 		    truncateCluster(cache[cache_pos].cluster_data, 0);
// 		}
// 	    }
// 	    else
// 		createNullCluster(&(cache[cache_pos].cluster_data));
// 	    
// 	    //Si el write es sobre una porcion del cluster, lo traigo entero
// 	    if(offset > 0 || size < boot->cluster_size)
// 	    {
// 		sectors *auxListSectors = NULL;
// 		auxListSectors = (sectors *) malloc(sizeof(sectors));
// 		auxListSectors->data = NULL;
// 		//Traigo el cluster que necesito
// 		readClusterNIPC(disk, boot, num_cluster, 0, boot->cluster_size, auxListSectors);
// 		//Lo guardo
// 		writeCacheCluster(cache_pos, path, num_cluster, 0, boot->cluster_size, auxListSectors);
// 	    }
// 	    
// 	    //Modifico el cluster en cuestion
// 	    writeCacheCluster(cache_pos, path, num_cluster, offset, size, listSectors);
// 	}
//     }
//     else	
// 	writeClusterNIPC(disk, boot, num_cluster, offset, size, listSectors);
// 
//     return 1;
// }
int writeClusterIntoCache(FILE* disk, bootRegion* boot, const char *path, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
{
    if(cache_enabled)
    {
    
    /*NL*/
				cacheFiles *cf = fileDescriptorsTable;
		    
		    while(cf != NULL && cf->data != NULL && strcmp(cf->data->path, path))
						cf = cf->sgt;
		    
		    if(cf != NULL && cf->data != NULL)
		    {
    
	unsigned int cache_pos, wrote = 0;
	
	for(cache_pos = 0; cache_pos < cant_cache_clusters && wrote == 0; cache_pos++)
	{
	    if(cf->data->cache[cache_pos].cluster_num == num_cluster)
	    {
		writeCacheCluster(&(cf->data->cache[cache_pos].cluster_data), path, num_cluster, offset, size, listSectors);
		wrote = 1;
	    }
	}
	
	if(wrote == 0)
	{
	    cache_pos = 0;
	    //getLRUCache(cache_pos);
	    cache_pos = rand() % cant_cache_clusters;
	    //Hago flush() del que voy a sobreescribir
	    if(cf->data->cache[cache_pos].cluster_data->data != NULL)
	    {
		if(cf->data->cache[cache_pos].cluster_num != 0)
		{
		    writeClusterNIPC(disk, boot, cf->data->cache[cache_pos].cluster_num, offset, size, cf->data->cache[cache_pos].cluster_data);
		    //Limpio el registro de cache
		    truncateCluster(cf->data->cache[cache_pos].cluster_data, 0);
		}
	    }
	    else
		createNullCluster(&(cf->data->cache[cache_pos].cluster_data));
	    
	    //Si el write es sobre una porcion del cluster, lo traigo entero
	    if(offset > 0 || size < boot->cluster_size)
	    {
		sectors *auxListSectors = NULL;
		auxListSectors = (sectors *) malloc(sizeof(sectors));
		auxListSectors->data = NULL;
		//Traigo el cluster que necesito
		readClusterNIPC(disk, boot, num_cluster, 0, boot->cluster_size, auxListSectors);
		//Lo guardo
	    cf->data->cache[cache_pos].cluster_num = num_cluster;
		writeCacheCluster(&(cf->data->cache[cache_pos].cluster_data), path, num_cluster, 0, boot->cluster_size, auxListSectors);
	    }
	    
	    //Modifico el cluster en cuestion
	    cf->data->cache[cache_pos].cluster_num = num_cluster;
	    writeCacheCluster(&(cf->data->cache[cache_pos].cluster_data), path, num_cluster, offset, size, listSectors);
    }
    else	
	writeClusterNIPC(disk, boot, num_cluster, offset, size, listSectors);
	}
    }
    else	
	writeClusterNIPC(disk, boot, num_cluster, offset, size, listSectors);

    return 1;
}

// int writeCacheCluster(unsigned int cache_pos, const char *path, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
// {
//     sectors *aux_sec;
//     int i;
//     unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size;
//         
//     div_sectors_int = offset / boot->bytes_per_sector;
//     div_sectors_resto = offset % boot->bytes_per_sector;
//     
//     div_total_size_int = size / boot->bytes_per_sector;
//     div_total_size_resto = size % boot->bytes_per_sector;
//     
//     if(div_total_size_int > 0 && div_total_size_resto == 0)
//     {
// 	div_total_size_resto = boot->bytes_per_sector;
// 	div_total_size_int--;
//     }
//     
//     sectors *q = listSectors;
//     sectors *aux_cache = cache[cache_pos].cluster_data;
//     
//     for(i=0;i< div_sectors_int && q != NULL;i++)
//     {
// 	q = q->sgt;
// 	aux_cache = aux_cache->sgt;
//     }
//     
//     while(i<boot->sectors_per_cluster && i<= div_total_size_int && q != NULL)
//     {
// 	if(i == div_total_size_int)
// 	    aux_size = div_total_size_resto;
// 	else
// 	    aux_size = boot->bytes_per_sector;
// 	
// // 	strncpy(aux_cache->data->sec, q->data->sec + div_sectors_resto,aux_size);
// 	memcpy((aux_cache->data->sec),(q->data->sec+div_sectors_resto),aux_size-div_sectors_resto);
// 	
// 	div_sectors_resto = 0;
// 	q = q->sgt;
// 	aux_cache = aux_cache->sgt;
// 	i++;
//     }
//     
//     cache[cache_pos].cluster_num = num_cluster;
//     cache[cache_pos].file_path = (char *) realloc (cache[cache_pos].file_path, sizeof(char) * strlen(path));
//     strcpy(cache[cache_pos].file_path, path);
//     
//     return 1;
// }
int writeCacheCluster(cluster **cluster_data, const char *path, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
{
    sectors *aux_sec;
    int i;
    unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size;
        
    div_sectors_int = offset / boot->bytes_per_sector;
    div_sectors_resto = offset % boot->bytes_per_sector;
    
    div_total_size_int = size / boot->bytes_per_sector;
    div_total_size_resto = size % boot->bytes_per_sector;
    
    if(div_total_size_int > 0 && div_total_size_resto == 0)
    {
	div_total_size_resto = boot->bytes_per_sector;
	div_total_size_int--;
    }
    
    sectors *q = listSectors;
    sectors *aux_cache = *cluster_data;
    
    for(i=0;i< div_sectors_int && q != NULL;i++)
    {
	q = q->sgt;
	aux_cache = aux_cache->sgt;
    }
    
    while(i<boot->sectors_per_cluster && i<= div_total_size_int && q != NULL && q->data != NULL && q->data->sec != NULL)
    {
	if(i == div_total_size_int)
	    aux_size = div_total_size_resto;
	else
	    aux_size = boot->bytes_per_sector;
	
// 	strncpy(aux_cache->data->sec, q->data->sec + div_sectors_resto,aux_size);
	memcpy((aux_cache->data->sec),(q->data->sec+div_sectors_resto),aux_size-div_sectors_resto);
	
	div_sectors_resto = 0;
	q = q->sgt;
	aux_cache = aux_cache->sgt;
	i++;
    }
    
    //cache[cache_pos].cluster_num = num_cluster;
    //cache[cache_pos].file_path = (char *) realloc (cache[cache_pos].file_path, sizeof(char) * strlen(path));
    //strcpy(cache[cache_pos].file_path, path);
    
    return 1;
}

int createNullCluster(sectors **listSectors)
{
    sector *aux_sec = (sector *) malloc(sizeof(sector));
    aux_sec->sec = (char *) malloc (sizeof(char) * boot->bytes_per_sector);
    unsigned int i = 0;
        
    while(i< boot->sectors_per_cluster)
    {
	truncateSector(&(aux_sec->sec), 0);
	addToList((gl *)*listSectors,aux_sec);
	aux_sec = (sector *) malloc (sizeof(sector));
	aux_sec->sec = (char *) malloc (sizeof(char) * boot->bytes_per_sector);
	i++;
    }
    
    return 1;
}

int flushCache(const char *path)
{
    if(cache_enabled)
    {
    /*NL*/
	cacheFiles *cf = fileDescriptorsTable;
		    
	while(cf != NULL && cf->data != NULL && strcmp(cf->data->path, path))
	    cf = cf->sgt;
	
	if(cf != NULL && cf->data != NULL)
	{
	    
	    unsigned int cache_pos;
	
	    for(cache_pos = 0; cache_pos < cant_cache_clusters ; cache_pos++)
	    {
		if(cf->data->cache[cache_pos].cluster_num != 0)
		{
		    //Escribo el cluster que no fue escrito
		    writeClusterNIPC(disk, boot, cf->data->cache[cache_pos].cluster_num, 0, boot->cluster_size, cf->data->cache[cache_pos].cluster_data);
		    //Limpio el registro de cache
		    truncateCluster(cf->data->cache[cache_pos].cluster_data, 0);
		    
		    cf->data->cache[cache_pos].cluster_num = 0;
		}
	    }
    
	}
    }
    return 1;
}

int hotfat_flush(const char *path, struct fuse_file_info *fi)
{
    
//  flushCache(path);
    
    return 0;
}


int hotfat_release(const char *path, struct fuse_file_info *fi)
{
    if(releaseCacheFile(path, fi->flags))
	return 0;
    else
	return 1;
}


int releaseCacheFile(const char *path, int fi_flags){

    cacheFiles *q = fileDescriptorsTable;
    
    while(q != NULL && q->data != NULL && strcmp(q->data->path, path))
	q = q->sgt;
    
    if(q != NULL && q->data != NULL)
    {
	    if ((fi_flags & O_WRONLY) == O_WRONLY || (fi_flags & O_RDWR) == O_RDWR)
	    {
    // 	    sem_post(&q->data->write_semaphore);
		    pthread_mutex_unlock(&(q->data->write_mutex));
		    
    // 	    sem_wait(&q->data->write_semaphore);
		    pthread_mutex_lock(&(q->data->write_mutex));
				    
		    directory *p = (directory *) malloc(sizeof(directory));
		    searchDirectory(path,root,&p);
		    if(p->data->type == 32)
		    {			
			//Save wrote as new size
			if(q->data->wrote != -1)
			{
			    p->data->size = q->data->wrote;
			    saveFAT(disk, boot, fatTablePointer);
			}
			
			char *aux_direct = (char *) malloc(sizeof(char) * 32+1);
			createDirectoryInput(&aux_direct, p->data);
			
			//Buscar dir padre
			char *pathFather = (char *) malloc(sizeof(char)*256);
			fatherName(path,pathFather);
			directory *direc = (directory *) malloc(sizeof(directory));
			searchDirectory(pathFather,root,&direc);

			
			if(saveDirectoryInputIntoLinkedClusters(direc->data->idCluster, aux_direct, 2))
			    free(aux_direct);
			else
			{
			    free(aux_direct);
			    return -1;
			}
			
		    }

		    q->data->wrote = -1;
	    // 	    sem_post(&q->data->write_semaphore);
		    pthread_mutex_unlock(&(q->data->write_mutex));
	}
	
	
    }
    else
	    return 0;

    if(q->data->cant_opens > 1)
	q->data->cant_opens = q->data->cant_opens - 1;
    else
    {
	cacheFiles *aux_file = fileDescriptorsTable;
	if(aux_file != NULL && aux_file->sgt == NULL)
	{
		    fileDescriptorsTable = (cacheFiles *) malloc(sizeof(cacheFiles));
		    fileDescriptorsTable->data = NULL;
		    fileDescriptorsTable->sgt = NULL;
    // 		sem_destroy(&(aux_file->data->write_semaphore));
		    pthread_mutex_destroy(&(aux_file->data->write_mutex));
		    int j;
		    for(j=0;j < cant_cache_clusters ;j++)
			free(aux_file->data->cache[j].cluster_data);
		    free(aux_file->data->cache);
		    free(aux_file->data->path);
		    free(aux_file->data);
		    free(aux_file);
	}
	else if(aux_file != NULL && aux_file->sgt != NULL)
	{
		    while(aux_file->sgt != NULL && aux_file->sgt->data != NULL && strcmp(aux_file->sgt->data->path, q->data->path))
			    aux_file = aux_file->sgt;
	    
		    if(!strcmp(aux_file->sgt->data->path, q->data->path))
		    {
			    aux_file->sgt = q->sgt;
    // 		    sem_destroy(&(q->data->write_semaphore));
			    pthread_mutex_destroy(&(aux_file->data->write_mutex));
			    int j;
			    for(j=0;j < cant_cache_clusters ;j++)
				free(q->data->cache[j].cluster_data);
			    free(q->data->cache);
			    free(q->data->path);
			    free(q->data);
			    free(q);
		    }
	}
	else
		    return 0;
    }

    
    return 1;
}


int saveDirectoryInputIntoSector(char **data_sector, char *new_dir_input, unsigned int mode)
{
    //mode == 1: new input
    //mode == 2: update input
    //mode == 3: delete input
    
    int j,z;
    directoryInput *dir = (directoryInput *) malloc(sizeof(directoryInput));
    
    for(j=0;j< boot->bytes_per_sector;j+=32)
    {
		if((*data_sector)[j] == 0 && mode == 1)
		{
			memcpy((*data_sector) +j,new_dir_input,32);
			return 1;
		}
		
		if(!strncmp((*data_sector) +j, new_dir_input, 11) && mode == 2)
		{
			memcpy((*data_sector) +j,new_dir_input,32);
			return 1;
		}
		
		if(!strncmp((*data_sector) +j, new_dir_input, 11) && mode == 3)
		{
			*new_dir_input = '\345';
			memcpy((*data_sector) +j,new_dir_input,32);
			return 1;
		}
    }
    
    return 0;
} 

int saveDirectoryInputIntoCluster(cluster *dirCluster, char *new_dir_input, unsigned int mode)
{
    cluster *q = dirCluster; 
    
    while (q != NULL && q->data != NULL && q->data->sec != NULL)
    {
	if(saveDirectoryInputIntoSector(&(q->data->sec), new_dir_input, mode))
	    return 1;
	
	q = q->sgt;
    }
    
    return 0;
}

int saveDirectoryInputIntoLinkedClusters(unsigned int cluster_num, char *new_dir_input, unsigned int mode)
{
    //mode == 1: new input
    //mode == 2: update input
    
    enum cluster_state state;
    sectors *listSectors;
    
    unsigned int aux_cluster_num;

    cache_enabled = 0;
    
    do
    {
	listSectors = (sectors *) malloc(sizeof(sectors));
	listSectors->data = NULL;
	listSectors->sgt = NULL;
	
	cluster_num = cluster_num + boot->first_data_cluster  - 2;
	readClusterFromCache(disk, boot, "", cluster_num, 0, boot->cluster_size, listSectors);
	if(saveDirectoryInputIntoCluster((cluster *)listSectors, new_dir_input, mode))
	{
	    writeClusterIntoCache(disk, boot, "", cluster_num, 0, boot->cluster_size, listSectors);
	    return 1;
	}
	
	cluster_num = cluster_num - boot->first_data_cluster  + 2;
	getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
	cluster_num = aux_cluster_num;
	
    } while((listSectors!=NULL)&&(state == used));
    
    cache_enabled = 1;
    
    return 0;
}

int hotfat_mkdir(const char *path, mode_t mode)
{
    unsigned int free_cluster_num;
   	char *name = (char *) malloc (sizeof(char) * 14);
    directoryInput *new_input = (directoryInput *) malloc (sizeof(directoryInput));
    new_input->name = (char *) malloc (sizeof(char) * 9);
    new_input->ext = (char *) malloc (sizeof(char) * 4);
// 	new_input->longName = (char *) malloc(sizeof(char)*14);
	
	//newName(path,new_input->name);
//     strcpy(new_input->name,path+1);
    
	newName(path,name);
	//strcpy(new_input->name,name);
	if(strlen(name)<8)
	{
		memcpy(new_input->name,name,strlen(name)+1);
		memset(new_input->name+strlen(name),'\0',1);
		strcpy(new_input->longName,"");
	}
	else
	{
		//memcpy(new_input->name,name,8);
		//memcpy(new_input->name,"\0",1);
// 		strncpy(new_input->name,name,8);


// 		memset(new_input->name,'\0',9);
// 		memcpy(new_input->name,name,8);
		memset(new_input->name, '\0', 9);
		memcpy(new_input->name,name,8);
// 		memset(new_input->longName,'\0',14);
		strcpy(new_input->longName,"");
		strcpy(new_input->longName,name);
// 		memcpy(new_input->longName,name,13);
		
		
		//memcpy(new_input->longName,name , strlen(name)+1);
	}

    new_input->size = boot->cluster_size;
    new_input->type = 16;
    
    
	//free(name);
	
// 	new_input->ext = "";
	strcpy(new_input->ext, "   ");
    
    getFreeCluster(freeClusters, &free_cluster_num);
    new_input->idCluster = free_cluster_num;
     
    char *aux_direct = (char *) malloc(sizeof(char) * 32+1);
	
    createDirectoryInput(&aux_direct, new_input);
    
    
    sectors *listSectors = (sectors *) malloc(sizeof(sectors));
    listSectors->data = NULL;
    listSectors->sgt = NULL;
    
    createNullCluster(&(listSectors));
    truncateCluster(listSectors, 0);
    writeClusterIntoCache(disk, boot, path, new_input->idCluster + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
    setUsedCluster(freeClusters, 0x0FFFFFF8, new_input->idCluster);
    
//     new_input->idCluster = 0;
    

    
	
	//char *aux_longDirect = (char *) malloc(sizeof(char) * 32+1);

		

    
    //Buscar dir padre
	char *pathFather = (char *) malloc(sizeof(char)*256);
	fatherName(path,pathFather);
    directory *q = (directory *) malloc(sizeof(directory));
    searchDirectory(pathFather,root,&q);
	//free(pathFather);
	if(strcmp(new_input->longName,""))
	{
// 		createLongNameInput(&aux_longDirect,new_input);
// 		saveDirectoryInputIntoLinkedClusters(q->data->idCluster, aux_longDirect, 1);
	}
	if(saveDirectoryInputIntoLinkedClusters(q->data->idCluster, aux_direct, 1))
    {
		if(q->content == NULL)
		{
			q->content = (directory *) malloc(sizeof(directory));
			q->content->data = NULL;
			q->content->content = NULL;
			q->content->sgt = NULL;
		}
		addToListWithSublist((glws *)q->content, new_input, NULL);
		free(aux_direct);
		//free(aux_longDirect);
		saveFAT(disk, boot, fatTablePointer);
		
	    q = NULL;
		free(name);
		free(pathFather);
		return 0;
    }
    else
    {
	free(aux_direct);
free(name);
free(pathFather);
	//free(aux_longDirect);
	return -1;
    }
    
    free(pathFather);
free(name);
    return -1;
}
    

void cacheDump(int signal)
{
    FILE* file_dump;
    if ((file_dump = fopen("cache_dump.txt", "a")) == NULL) {
	    return;
    }
        
    fprintf(file_dump, "-------- HOTFAT's CACHE DUMP --------\n");
    
    cacheFiles *q = fileDescriptorsTable;
    unsigned int cache_pos = 0, clus = 0, sect = 0, byte = 0;
    while(q != NULL && q->data != NULL && q->data->cache != NULL)
    {
	fprintf(file_dump, "- Archivo: %s \n", q->data->path);
	

	    if(q->data->cache[cache_pos].cluster_data != NULL && q->data->cache[cache_pos].cluster_num != 0)
	    {
		fprintf(file_dump, "-- Bloque: %d KB\n", boot->cluster_size / 1024 );		
    fprintf(file_dump, "-- Cantidad de Bloques en cache: %u \n", cant_cache_clusters);
    	for(cache_pos = 0; cache_pos < cant_cache_clusters; cache_pos++)
	{
		fprintf(file_dump, "---- Content Bloque #%u: \n", cache_pos);
		sect=0;
		cluster *sector_data = q->data->cache[cache_pos].cluster_data;
		while(sect< boot->sectors_per_cluster && sector_data != NULL && sector_data->data != NULL )
		{
      if(sector_data->data->sec != NULL)
		    for(byte=0;byte<boot->bytes_per_sector;byte++)
           fprintf(file_dump, "%c", (int) (sector_data->data->sec + byte));
		    
		    sector_data = sector_data->sgt;
		    sect++;
		}     
      } 
      fprintf(file_dump, "--- ***************************** ---\n\n");
	    }

	
	q = q->sgt;
    }
    fprintf(file_dump, "-------------------------------------\n");
    fclose(file_dump);
    return;
} 

int searchPath(directory *dir, char* name, directory **result)
{
	if(strcmp(name, "") != 0)
	{
		//int lenght = (int)strlen(name);
		directory *p = dir;
		
		while (p != NULL)
		{
			if(strcmp(p->data->longName,"") == 0)
			{
			    char *nameWithOutSpaces = (char *) malloc(sizeof(char) * 9);
			    strcpy(nameWithOutSpaces, p->data->name);
			    rtrimHOTFAT(nameWithOutSpaces,' ');
			    if((p->data->type == 16  || p->data->type == 32) && (!strncmp(nameWithOutSpaces,name,strlen(nameWithOutSpaces))))
			    {
				    *result=p;
				    free(nameWithOutSpaces);
				    break;
			    }
			    free(nameWithOutSpaces);
			}
			else
			{
			    char *nameWithOutSpaces = (char *) malloc(sizeof(char) * 9);
			    strcpy(nameWithOutSpaces, p->data->longName);
			    rtrimHOTFAT(nameWithOutSpaces,' ');
			    if((p->data->type == 16  || p->data->type == 32) && (!strncmp(nameWithOutSpaces,name,strlen(nameWithOutSpaces))))
			    {
				    *result=p;
				    free(nameWithOutSpaces);
				    break;
			    }
			    free(nameWithOutSpaces);
			}
			
			p = p->sgt;
		} 
		if(*result != p)
			*result = NULL;
	}
	else 
		*result = dir;
    return 1;
}

int searchPath2(directory *dir, char* name, directory **result, directory **last)
{
	directory *auxlast = dir;
	int first = 0;
	
	if(strcmp(name, "") != 0)
	{
		//int lenght = (int)strlen(name);
		directory *p = dir;
		
		while (p != NULL)
		{
			if(strcmp(p->data->longName,"") == 0)
			{
			    char *nameWithOutSpaces = (char *) malloc(sizeof(char) * 9);
			    strcpy(nameWithOutSpaces, p->data->name);
			    rtrimHOTFAT(nameWithOutSpaces,' ');
			    if((p->data->type == 16  || p->data->type == 32) && (!strncmp(nameWithOutSpaces,name,strlen(nameWithOutSpaces))))
			    {
				    *result=p;
				    *last = auxlast;
				    free(nameWithOutSpaces);
				    break;
			    }
			    free(nameWithOutSpaces);
			}
			else
			{
			    char *nameWithOutSpaces = (char *) malloc(sizeof(char) * 9);
			    strcpy(nameWithOutSpaces, p->data->longName);
			    rtrimHOTFAT(nameWithOutSpaces,' ');
			    if((p->data->type == 16  || p->data->type == 32) && (!strncmp(nameWithOutSpaces,name,strlen(nameWithOutSpaces))))
			    {
				    *result=p;
				    free(nameWithOutSpaces);
				    break;
			    }
			    free(nameWithOutSpaces);
			}
			
			if(first == 0)
			{
				auxlast = auxlast->sgt;
				first++;
			}
			
			p = p->sgt;
		} 
		if(*result != p)
			*result = NULL;
		else 
		if(auxlast == p)
			*last = NULL;
	}
	else 
	{
		*result = dir;
		*last = NULL;
	}
    return 1;
    
    
//     int lenght = (int)strlen(name);
// 	int first = 0;
//     directory *p = dir;
// 	directory *auxlast = dir;
//     while (p != NULL)
//     {
// 		if((p->data->type == 16  || p->data->type == 32) && (!strncmp(p->data->name,name,lenght)))
// 		{
// 			*result=p;
// 			*last = auxlast;
// 			break;
// 		}
// 		p = p->sgt;
// 		if(first)
// 			auxlast = auxlast->sgt;
// 		first++;
//     } 
// 
// 	if(*result != p)
// 		*result = NULL;
// 	else 
// 		if(auxlast == p)
// 			*last = NULL;
	
	
    return 1;
}

int cutPath(const char *path,char *directory[],int *count)
{
    int i;
    char *aux = (char *) malloc(sizeof(char)*9);
    strcpy(aux,path);
	*count = 1;
    directory[0] = strtok(aux,"/");
    for(i = 1; (directory[i]= strtok(NULL, "/"));i++,(*count)++);
    
    return 1;
}

int cutPath2(const char *path,char *directory,char* finalPath)
{
	char *aux = (char *) malloc(sizeof(char)*256);
	if(strlen(path)>1)
	{
		strcpy(aux,path);
		strcpy(directory,strtok(aux,"/"));
		strcpy(finalPath,path+(strlen(directory)+1));
	}
	else
		strcpy(finalPath,path);
		
	free(aux);
    return 1;
}

int newName(const char* path, char *name)
{
	char *primero = (char *) malloc(sizeof(char)*14);
	char *resto= (char *) malloc(sizeof(char)*256);

	cutPath2(path,primero,resto);
	while(strcmp(resto,"") != 0)
		cutPath2(resto,primero,resto);
	
	strcpy(name,primero);
	
	name = rtrimHOTFAT(name,'/');
	name = ltrimHOTFAT(name,'/');

	free(primero);
	free(resto);
	
	return 1;
}

int fatherName(const char *path,char *fatherPath)
{
	char *primero = (char *) malloc(sizeof(char)*8);
	char *resto= (char *) malloc(sizeof(char)*256);
	char *name= (char *) malloc(sizeof(char)*256);
			
	newName(path,name);

	cutPath2(path,primero,resto);
	if(strcmp(resto,"")!=0)
	{
		sprintf(fatherPath,"/%s",primero);
		while(strcmp(resto+1,name) != 0)
		{
			cutPath2(resto,primero,resto);
			sprintf(fatherPath,"%s/%s",fatherPath,primero);
		}
	}
	else
	{
		strcpy(fatherPath,"/");
	}
	
	free(primero);
	//free(resto);
	free(name);
	
	
 	return 1;
}

int searchDirectory(const char* path, directory *root, directory **dir)
{
	if(strcmp(path,"/") != 0)
	{
		char *primero = (char *) malloc(sizeof(char)*14);
		char *resto= (char *) malloc(sizeof(char)*256);
		cutPath2(path,primero,resto);
		directory *content_search = root;

		int flag = 0;
		
		while(strcmp(resto,"") != 0 || flag < 1)
		{
			searchPath(content_search->content,primero,dir);
			if(*dir == NULL)
				break;
			content_search = *dir;
			if(strcmp(resto,"") != 0)
				cutPath2(resto,primero,resto);
			else
				flag++;
		}
		
		free(primero);
		free(resto);
	}
	else
		*dir = root;
	return 1;
}

int getDirectory(const char* path, directory *root, directory **dir)
{
	char *primero = (char *) malloc(sizeof(char)*13);
	char *resto= (char *) malloc(sizeof(char)*512);
	cutPath2(path,primero,resto);
	directory *last = (directory *) malloc(sizeof(directory*));
	directory *content_search = root;
	int flag = 0;
	while(strcmp(resto,"") != 0 || flag < 1)
	{
		searchPath2(content_search->content,primero,&(*dir),&last);
		content_search = *dir;
		if(strcmp(resto,"") != 0)
			cutPath2(resto,primero,resto);
		else
			flag++;
	}
	
	if(last != NULL)
		last->sgt = (*dir)->sgt;
	else
	{
		char *fatherPath = (char *) malloc(sizeof(char) * 256);
		fatherName(path, fatherPath);
		directory *fatherDirectory = (directory *) malloc(sizeof(directory));
		searchDirectory(fatherPath, root, &fatherDirectory);
		free(fatherPath);		
		if((*dir)->sgt != NULL)
			fatherDirectory->content = (*dir)->sgt;
		else
			fatherDirectory->content = NULL;
	}

	return 1;
}

int youMakeMeFiller(directory *dir,void *buf, fuse_fill_dir_t *filler)
{
	char *nameWithoutSpace = (char *) malloc(sizeof(char)*14);
	if(strcmp(dir->data->longName,"") == 0)
	{
	    strcpy(nameWithoutSpace, dir->data->name);
	    rtrimHOTFAT(nameWithoutSpace,' ');
	}
	else
	{
	    strcpy(nameWithoutSpace, dir->data->longName);
	    rtrimHOTFAT(nameWithoutSpace,' ');
	}
	if(dir->data->type == 16)
		(*filler)(buf,nameWithoutSpace,NULL,0);
	
	if(dir->data->type == 32)
	{
		if(strncmp(dir->data->ext,"   ",3) != 0 && strcmp(dir->data->ext,"") != 0)
		{
			char *fullName = (char *) malloc(sizeof(char)*21);
			char *extWithoutSpace = (char *) malloc(sizeof(char)*4);
			strcpy(extWithoutSpace, dir->data->ext);
			rtrimHOTFAT(extWithoutSpace,' ');
			sprintf(fullName,"%s.%s",nameWithoutSpace,extWithoutSpace);
			(*filler)(buf,fullName,NULL,0);
			
			free(extWithoutSpace);
			free(fullName);
		}
		else
			(*filler)(buf,nameWithoutSpace,NULL,0);
	}

	free(nameWithoutSpace);
	return 1;
}

int getAttrOfDir(directory *dir, const char *path,struct stat *stbuf)
{
	char *nameWithoutSpace = (char *) malloc(sizeof(char)*14);
	char *name = (char *) malloc(sizeof(char)*257);

	if(strcmp(dir->data->longName,"") == 0)
	{
		strcpy(nameWithoutSpace, dir->data->name);
		rtrimHOTFAT(nameWithoutSpace,' ');
	}
	else
	{
		strcpy(nameWithoutSpace, dir->data->longName);
		nameWithoutSpace = rtrimHOTFAT(nameWithoutSpace,' ');
	}
	
	newName(path,name);
	if(strncmp(name,nameWithoutSpace,strlen(nameWithoutSpace)) == 0)
	{
		if(dir->data->type == 16)
		{
			stbuf->st_mode = S_IFDIR | 0755;
			stbuf->st_nlink = 2;
			stbuf->st_size =boot->cluster_size;
		}
		if(dir->data->type == 32)
		{
			stbuf->st_mode = S_IFREG | 0644;
			stbuf->st_nlink = 1;
			stbuf->st_size = dir->data->size;
		
		}
	}
	
	free(name);
	free(nameWithoutSpace);

	return 1;
}

char* rtrimHOTFAT(char* string, char junk)
{
    char* original = string + strlen(string);
    while(*--original == junk);
    *(original + 1) = '\0';
    return string;
}

char* ltrimHOTFAT(char *string, char junk)
{
    char* original = string;
    char *p = original;
    int trimmed = 0;
    do
    {
        if (*original != junk || trimmed)
        {
            trimmed = 1;
            *p++ = *original;
        }
    }
    while (*original++ != '\0');
    return string;
}

int hotfat_rmdir(const char* path)
{
	directory *dir = (directory *) malloc(sizeof(directory));
	directory *fatherDirectory =  (directory *) malloc(sizeof(directory));
	char *dirFat = (char *) malloc(sizeof(char)*512);
	char *fatherPath = (char *) malloc(sizeof(char)*512);
	

	searchDirectory(path,root,&dir);
	
	directory *q = dir->content;
	while(q != NULL && q->data != NULL)
	{
		char *nameWithoutSpace = (char *) malloc(sizeof(char) * 9);
		strcpy(nameWithoutSpace, q->data->name);
		if(strcmp(rtrimHOTFAT(nameWithoutSpace, ' '),".") && strcmp(rtrimHOTFAT(nameWithoutSpace, ' '),".."))
		{
			free(nameWithoutSpace);
			return -ENOENT;
		}
		free(nameWithoutSpace);
		q = q->sgt;
	}
	
	fatherName(path,fatherPath);
	searchDirectory(fatherPath,root,&fatherDirectory);
	createDirectoryInput(&dirFat,dir->data);
	saveDirectoryInputIntoLinkedClusters(fatherDirectory->data->idCluster,dirFat,3);
	if(!getDirectory(path,root,&dir))
		return -ENOENT;
	
// 	if(dir->content == NULL)
// 	{
// 		fatherName(path,fatherPath);
// 		searchDirectory(fatherPath,root,&fatherDirectory);
// 		createDirectoryInput(&dirFat,dir->data);
// 		saveDirectoryInputIntoLinkedClusters(fatherDirectory->data->idCluster,dirFat,3);
// 		if(!getDirectory(path,root,&dir))
// 			return -ENOENT;
// 	}
// 	else
// 		return -ENOENT;
	
	return 0;
}

int hotfat_unlink(const char* path)
{
	directory *dir = (directory *) malloc(sizeof(directory));
	directory *fatherDirectory =  (directory *) malloc(sizeof(directory));
	char *dirFat = (char *) malloc(sizeof(char)*33);
	char *fatherPath = (char *) malloc(sizeof(char)*512);
	

	searchDirectory(path,root,&dir);
	
	if(dir->content == NULL)
	{
		fatherName(path,fatherPath);
		searchDirectory(fatherPath,root,&fatherDirectory);
		createDirectoryInput(&dirFat,dir->data);
		saveDirectoryInputIntoLinkedClusters(fatherDirectory->data->idCluster,dirFat,3);
		if(!getDirectory(path,root,&dir))
			return -ENOENT;
	}
	else
		return -ENOENT;

	return 0;
}

int hotfat_rename(const char *path, const char *newPath)
{
	char *name = (char *) malloc(sizeof(char) * 512);
	char *dirFat = (char *) malloc(sizeof(char)*33);
	char *fatherPath = (char *) malloc(sizeof(char)*512);
	directory *dir = (directory *) malloc(sizeof(directory));
	directory *fatherDirectory =  (directory *) malloc(sizeof(directory));
	directory *newDir = (directory *) malloc(sizeof(directory));
	
	if(searchDirectory(path,root,&newDir) == -ENOENT)
	{
		//Búsco el directorio y el del padre,, con el mio obtengo el dirfat(los 32) y con el del padre escrivo en la fat con el 345
		fatherName(path,fatherPath);
		searchDirectory(path,root,&dir);
		createDirectoryInput(&dirFat,dir->data);
		searchDirectory(fatherPath,root,&fatherDirectory);
		saveDirectoryInputIntoLinkedClusters(fatherDirectory->data->idCluster,dirFat,3);
		
		
		//Búsco el directorio viejo y lo quito
		directory *oldDir= (directory *) malloc(sizeof(directory));
		getDirectory(path,root,&oldDir);
		//Búsco el directorio padre del nuevo directorio
		newDir = (directory *) malloc(sizeof(directory));
		fatherName(newPath,fatherPath);
		searchDirectory(fatherPath,root,&newDir);
		
		//Agrego el nuevo directorio con el nuevo nombre
		newName(newPath,name);
		strcpy(oldDir->data->name,name);
		if(newDir->content == NULL)
			newDir->content = (directory *) malloc(sizeof(directory));
		addToListWithSublist((glws *)newDir->content,oldDir->data,(glws *)oldDir->content);
		
		
		createDirectoryInput(&dirFat,oldDir->data);
		searchDirectory(fatherPath,root,&fatherDirectory);
		saveDirectoryInputIntoLinkedClusters(fatherDirectory->data->idCluster,dirFat,1);	
	}
	else
	{
		return -EEXIST;
	}
	
	
    return 0;
}

int hotfat_getattr(const char *path, struct stat *stbuf)
{
    int res = 0, aux_size = 0;
    
    if(strncmp(path,"/.Trash",7) != 0 && strcmp(path,"/.hidden") != 0 && strncmp(path,"/.xdg-volume",11) != 0 && strncmp(path,"/autorun.inf",11) != 0 && strncmp(path,"/.directory",10) != 0){

        if(strcmp(path, "/") == 0)
		{
			stbuf->st_mode = S_IFDIR | 0755;
			stbuf->st_nlink = 2;
		}   	 
		else
		{
			directory *q = (directory *) malloc(sizeof(directory));
			searchDirectory(path,root,&q);
			if(q!=NULL)
				getAttrOfDir(q,path,stbuf);
			else 
				return -ENOENT;
		    q = NULL;
		}
    }
    

	
	
    return 0;
}

int hotfat_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi)
{
	filler(buf,".",NULL,0);
	filler(buf,"..",NULL,0);
	directory *q = root->content;
	if(strcmp(path, "/") != 0)
	{

		directory *dir = (directory *) malloc(sizeof(directory));
		searchDirectory(path,root,&dir);
		if(dir == NULL)
			return -ENOENT;
		q = dir->content;
	}
	while(q!=NULL)
	{
		youMakeMeFiller(q,buf,&filler);
		q = q->sgt;
	}

	q = NULL;
	return 0;
}


int readSectorFAT(FILE* disk, bootRegion *boot, unsigned int num_sector, unsigned int offset, unsigned int size, char **data_sector, int iSocketConectado)
{
    char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int) + 1);
    InfoIPC sInfoIPC;
    memset(num_sector_str, '\0', sizeof(char) * sizeof(unsigned int) + 1);
    sprintf(num_sector_str, "%u", num_sector);
    sInfoIPC.payLoadLength = strlen(num_sector_str) + 1;
    generarStructIPC(num_sector_str,READ_SECTOR_REQUEST,&sInfoIPC);
    enviarIPC(iSocketConectado ,&sInfoIPC);
    free(num_sector_str);
    
    InfoIPC rInfoIPC;
    unsigned int nro_pedido, nro_sector;
    recibirIPC(iSocketConectado,&rInfoIPC);
    if(rInfoIPC.payLoadDescriptor == NUMEROPEDIDO)
    {
	nro_pedido = atoi(rInfoIPC.payload);
    
	recibirIPC(iSocketConectado,&rInfoIPC);
	if(rInfoIPC.payLoadDescriptor == RTA_READ_SECTOR_REQUEST)
	{
	    nro_sector = atoi(rInfoIPC.payload);
	    recibirIPC(iSocketConectado,&rInfoIPC);
	    memcpy(*data_sector, rInfoIPC.payload, rInfoIPC.payLoadLength);
	}
    }
    
//     InfoIPC rInfoIPC;
//     char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int)+ 1);
//     
//     sprintf(num_sector_str, "%u", num_sector);
//     rInfoIPC.payLoadLength = strlen(num_sector_str) + 1;
//     generarStructIPC(num_sector_str,READ_SECTOR_REQUEST_LAST,&rInfoIPC);
//     enviarIPC(iSocketConectado,&rInfoIPC);
//     
//     recibirIPC(iSocketConectado,&rInfoIPC);
//     memcpy(*data_sector, rInfoIPC.payload, rInfoIPC.payLoadLength);
//     
//     free(rInfoIPC.payload);
//     free(num_sector_str);
	
    return 1;
}

int writeSectorFAT(FILE* disk, bootRegion *boot, unsigned int num_sector, unsigned int offset, unsigned int size, char *data_sector, int iSocketConectado)
{
    InfoIPC rInfoIPC;
    char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int)+ 1);
    
    char *data_send = (char *) malloc(sizeof(char) * size);
    sprintf(num_sector_str, "%u", num_sector);
    rInfoIPC.payLoadLength = strlen(num_sector_str) + 1;
    generarStructIPC(num_sector_str,WRITE_SECTOR_REQUEST,&rInfoIPC);
    enviarIPC(iSocketConectado,&rInfoIPC);
    
    recibirIPC(iSocketConectado,&rInfoIPC);
    if(rInfoIPC.payLoadDescriptor == RTA_WRITE_SECTOR_REQUEST)
    {
	rInfoIPC.payLoadLength = 512;
	memcpy(data_send, data_sector + offset, size);
	generarStructIPC(data_send,SET_SECTORES,&rInfoIPC);
	enviarIPC(iSocketConectado,&rInfoIPC);
	
	recibirIPC(iSocketConectado,&rInfoIPC);
	if(rInfoIPC.payLoadDescriptor != RTA_SET_SECTORES)
	{
	    close(iSocketConectado);
	    free(rInfoIPC.payload);
	    free(num_sector_str);
	    free(data_send);
	    return -1;
	}
    else
	return -1;
    
    }
    
    free(rInfoIPC.payload);
    free(num_sector_str);
    free(data_send);
    
    return 1;
    
}
